//============================================================================================
/**
 * @file	pokethlon.c
 * @brief	ポケスロン
 * @author	Nozomu Saito
 */
//============================================================================================

#define POKETHLON_MEM_SIZE	(0x72000)

#include "common.h"
#include "pokethlon.h"
#include "application/pokethlon_frame.h"
#include "comm_command_pkthln.h"
#include "system/procsys.h"
#include "system/render_oam.h"
#include "pkthln_frame_seq_def.h"
#include "comm_command_pkthln_func.h"

#include "system/snd_tool.h"
#include "system/snd_play.h"
#include "system/pm_str.h"
#include "system/pmfprint.h"
#include "system/wipe.h"

#include "pkthln_poke_idx.dat"
#include "field/pair_poke_idx.h"

#include "pkthln_event/event_se_def.h"

#include "field/pair_poke_info.h"
#include "field/eventflag.h"
#include "poketool/monsno.h"

#include "field/evwkdef.h"
#include "fielddata/script/saveflag.h"

#include "application/pokethlon_rankdata.h"

//↓for MakeNpc
#include "field/fieldobj_code.h"	//for OBJCODE
#include "npc_obj_code.dat"
#include "system/msgdata_util.h"
#include "msgdata/msg.naix"
#include "msgdata/msg_pokethlon.h"
#include "gflib/strbuf_family.h"
//↑for MakeNpc

#include "savedata/bonguri.h"		//for BonguriSave_

#define POKE_RANGE	(80)

#define REC_WAIT		(60)
#define COUNT_MAX		(120)

#define COUNTDOWN_MARGINE	(21)
#define START_COUNT_MAX		(COUNTDOWN_MARGINE*3)

#define POS_MARKER_TCB_PRI	(1)

#define ACTION_ADD_MAX		(9999)
#define ALONE_CRS_ID_NUM	(5)		//非通信コースの数（マスター以外）
#define COMM_CRS_ID_NUM	(5)		//通信コースの数（マスター以外）

#define CRS_NPC_NUM			(5)		//各コースに５名のＮＰＣ
#define COMM_ALL_NPC_NUM			( CRS_NPC_NUM * COMM_CRS_ID_NUM )		//マスターコース時のNPC総数
#define ALLSTAR_NPC_OFS			( CRS_NPC_NUM * CRS_ID_NUM )		//オールスターオフセット
#define MAS_CRS_OFS	( CRS_NPC_NUM * ALONE_CRS_ID_NUM )

#define MAS_NO_NUM	(10)		//マスターコースタイプ数

//デバッグ
#ifdef PM_DEBUG
///#define DEBUG_NPC_POKE		//有効でNPCポケナンバーデバッグ
///#define DEBUG_INFINIT			//無限ポケスロンデバッグ
#endif


typedef void (*PKTHLN_DRAW)(PKTHLN_PTR work);

typedef enum {
	COMP_LARGE,
	COMP_SMALL,
}COMP_MODE;

typedef enum {
	PKTHLN_FRM_SEQ_MAIN,
	PKTHLN_FRM_SEQ_SYNCSTART,
	PKTHLN_FRM_SEQ_SYNCWAIT,
	PKTHLN_FRM_SEQ_EVT_END_SYNCSTART,
	PKTHLN_FRM_SEQ_EVT_END_SYNCWAIT,
}MAIN_SEQ;

typedef enum{
	SAVE_BEST_ONE = 0,
	SAVE_BEST_TWO = 1,
	SAVE_BEST_THREE = 2,
	SAVE_BEST_FOUR = 3,
	SAVE_BEST_FIVE = 4,
	NETID_BASE = 5,
	NEW_DATA_NETID_ZERO = 5,
	NEW_DATA_NETID_ONE = 6,
	NEW_DATA_NETID_TWO = 7,
	NEW_DATA_NETID_THREE = 8,
}DATA_TYPE_CODE;

typedef struct SORT_DATA_tag
{
///	int TypeCode;	//DATA_TYPE_CODE
	//セーブに入っていたデータの場合SAVE_BEST〜をセット、新データの場合はネットＩＤに従い、NEW_DATA_NETID〜をセット
	u16 Record;			//ソート対象となる実データ
	u16 FrmMnsNo[ENTRY_MAX];
	u32 TrID;
	u16 TrName[BUFLEN_PERSON_NAME];
	u8 CountryCode;
	u8 dummy[3];
}SORT_DATA;

/**
//競技結果格納構造体
typedef struct EVT_RSLT_DATA_tag
{
	int DataNum;
	BOOL IconValid;
	RESULT_DATA Result[ENTRY_MEMBER_NUM_MAX*ENTRY_MAX];
}EVT_RSLT_DATA;
*/
//シーケンス構造体
typedef struct SEQ_DATA_tag
{
	const PKTHLN_FUNC *FuncTbl;
	u8 TblSize;
	u8 SubSeq;				//ムーブ関数内サブシーケンサ
	u8 TblIdx;
	u8 TblIdxReq;
}SEQ_DATA;

//シーケンスコントローラ
typedef struct SEQ_CONTROLER_tag
{
	SEQ_DATA		*ActiveSeqData;		//シーケンスデータポインタ
	u32				SynchroID;
	MAIN_SEQ		MainSeq;

	u32				ChgReqFlg;		//ムーブ関数の変更リクエストフラグ
}SEQ_CONTROLER;

typedef struct PKTHLN_COMM_COMMON_DATA_tag
{
	int EventNo[PKTHLN_EVT_MAX_COMM];
	int CourseID;
	COMMON_PLAYER_DATA PlayerData[ENTRY_MEMBER_NUM_MAX];
}PKTHLN_COMM_COMMON_DATA;

typedef struct EVENT_RESULT_DATA_tag
{
	u16 Data;	//2byte
	u16 dummy;	//2byte
}EVENT_RESULT_DATA;			//計4byte

typedef struct EVENT_RESULT_DATA_ALLtag
{
	EVENT_RESULT_DATA All[ENTRY_MEMBER_NUM_MAX];	//16byte
	u8 dummy[20];									//20byte
}EVENT_RESULT_DATA_ALL;		//計36byte

typedef struct POS_MARKER_tag
{
	BOOL Valid;
	//ポケモンアクターポインタ
	POKE_ACT_PTR PokePtr;
	//▼アクター
	CLACT_WORK_PTR ActPtr;
	//TCBポインタ
	TCB_PTR TcbPtr;
}POS_MARKER;

typedef struct POS_MARKER_MNG_tag
{
	u32 NowEntry;
	POS_MARKER Marker[ENTRY_MAX];
}POS_MARKER_MNG;

//ポケスロンワーク
typedef struct POKETHLON_WORK_tag
{
	POKETHLON_ENTRY_DATA	_PokeEntryData[ENTRY_MEMBER_NUM_MAX][ENTRY_MAX];
	const POKETHLON_FUNC_TBL *FuncTbl;
	PTH_EVENT_WORK *EventWork;			//競技ワークポインタ

	u8 EvtOrg[PKTHLN_EVT_MAX_COMM];		//今回の競技

	u8 MyIndex;
	u8 SubSeq;
	u8 PlayerNum;
	u8 DataSendNum;

	int EventCounter;
	BOOL DrawFlg;
///	PKTHLN_SEQ PokethlonSeq;
	PKTHLN_LINK_DATA LinkData;
	PROC * PokeSelectProc;
	int HeapID;
	COMMPACK_PTR CommPackPtr;
	COMM_EVENT_COMMON_DATA EvtComCmnData;			//競技用通信データ
///	PTH_MOVE_CNT_PTR	MoveCntPtr;
	SEQ_CONTROLER	SeqCnt;
	SEQ_DATA		FrameSeq;
	SEQ_DATA		EventSeq;

	PKTHLN_DRAW		PokethlonDraw;

	PKTHLN_COMM_COMMON_DATA	CommCmnData;	//ポケスロン参加プレーヤー共有データ
	MYSTATUS*	MyStatus/*[ENTRY_MEMBER_NUM_MAX]*/;	//マイステータス4人分のアドレスポインタ

	EVENT_RESULT_DATA RsltDataOrg[ENTRY_MEMBER_NUM_MAX];	//競技の結果を格納するバッファ　通信で送る
	EVENT_RESULT_DATA_ALL RsltDataAll;		//競技の結果の通信で受け取るバッファ

///	EVT_RSLT_DATA ResultData;		//競技結果格納場所
	RSLT_PTR	Result;
	PKTHPOKE_PARAM PokeParam[ENTRY_MEMBER_NUM_MAX][ENTRY_MAX];

	//カウントダウン
	CLACT_WORK_PTR CDActPtr;
	u8 StartCount;
	u8 CountSeq;
	u16 CountYOfs;
	//ニューレコード
	CLACT_WORK_PTR NRActPtr;
	//競技終了前カウンタ
	CLACT_WORK_PTR LastCntPtr;
	//レコードＢＭＰ表示ＢＧマスク
	int RecBGMask;
	//ペンOBJ
	CLACT_WORK_PTR PenActPtr[ENTRY_MAX];
	u8 PenNum;
	u8 PenSeq;
	//競技数
	u8 EventMax;
	//サウンド用初検出テンポラリ(ラスト3秒ＳＥ時に使用)
	u8 SeTmpSec;

	PKTHLN_SVSET_DATA	SvSetData;


	//ランキング転送元ワーク
	PKTH_RNK_DATA RankDataOrg;

	//ランキングセーブワーク
	PKTH_RNK_DATA RankData[ENTRY_MEMBER_NUM_MAX];
	//ランキングワーク
///	PKTH_RNK_DATA RankDataDif[ENTRY_MEMBER_NUM_MAX];

	PKTHLN_POKE_RSLT EvtActionTmp[ENTRY_MAX];
	PKTHLN_POKE_RSLT EvtActionTmpBuf[ENTRY_MEMBER_NUM_MAX][ENTRY_MAX];

	int PlayTime;
	u16 FrameCount;
	u16 CheckRecord;
	BOOL OpeningStart;

	POS_MARKER_MNG	PosMarkerMng;

	void *JuiceData;
	void *AllJuiceData;

	REC_CALL_BACK	RecordCallBack;

}POKETHLON_WORK;


typedef struct NPC_DATA_tag
{
	u16 MonsNo[ENTRY_MAX];
	u8 NameGmmIdx;
	u8 MsgGmmIdx;
}NPC_DATA;

#ifdef PM_DEBUG
int SysHeap = 0;
int SaveHeap = 0;
int AppHeap = 0;
int PkthHeap = 0;
extern DEBUG_PKTHLN_WORK DebugPkthlnWk;
#endif

extern PROC_RESULT PKTHLN_PokeSelect_Init(PROC * proc, int * seq);
extern PROC_RESULT PKTHLN_PokeSelect_Main(PROC * proc, int * seq);
extern PROC_RESULT PKTHLN_PokeSelect_End(PROC * proc, int * seq);

///関数前方宣言///
static PTH_RC DummyInitFunc(PKTHLN_PTR work, void *param);
static BOOL DummyFunc(PKTHLN_PTR work, void *param);

static BOOL FuncInit(PKTHLN_PTR work);
static BOOL PokethlonMain(PKTHLN_PTR work);
static void InitSeqData(const PKTHLN_FUNC *inFuncTbl, SEQ_DATA *outSeqData);
static void SetMyStatus(PKTHLN_PTR work);
static MYSTATUS *GetMyStatus(MYSTATUS *mystatus_array, const int inIdx);

//描画
static void	EventDraw(PKTHLN_PTR work);
//Vブランク関数
static void VBlankFunc( void * work );

//シーケンス関数
static BOOL FrameFunc_ShareEventNo(PKTHLN_PTR work, u8 *seq);
static BOOL FrameFunc_PokemonSelect(PKTHLN_PTR work, u8 *seq);

static BOOL FrameFunc_WaitPokeSel(PKTHLN_PTR work, u8 *seq);

static BOOL FrameFunc_PokemonEntry(PKTHLN_PTR work, u8 *seq);
static BOOL FrameFunc_ParentSharePokemon(PKTHLN_PTR work, u8 *seq);
static BOOL FrameFunc_SetMyStatus(PKTHLN_PTR work, u8 *seq);
static BOOL FrameFunc_SendMyRankData(PKTHLN_PTR work, u8 *seq);
///static BOOL FrameFunc_ParentShareRankData(PKTHLN_PTR work, u8 *seq);

static BOOL FrameFuncOpeningSet(PKTHLN_PTR work, u8 *seq);
static BOOL FrameFuncOpeningInit(PKTHLN_PTR work, u8 *seq);
static BOOL FrameFuncOpeningMain(PKTHLN_PTR work, u8 *seq);
static BOOL FrameFuncOpeningEnd(PKTHLN_PTR work, u8 *seq);

static BOOL FrameFuncEvtCallSet(PKTHLN_PTR work, u8 *seq);
static BOOL FrameFuncEvtCallInit(PKTHLN_PTR work, u8 *seq);
static BOOL FrameFuncEvtCallMain(PKTHLN_PTR work, u8 *seq);
static BOOL FrameFuncEvtCallEnd(PKTHLN_PTR work, u8 *seq);

static BOOL FrameFunc_EventSet(PKTHLN_PTR work, u8 *seq);
static BOOL FrameFunc_EventInit(PKTHLN_PTR work, u8 *seq);
///static BOOL FrameFunc_ChangeEventCommand(PKTHLN_PTR work, u8 *seq);
static BOOL FrameFunc_EventShareData(PKTHLN_PTR work, u8 *seq);
static BOOL FrameFunc_EventMain(PKTHLN_PTR work, u8 *seq);
static BOOL FrameFunc_EventRsltShareStart(PKTHLN_PTR work, u8 *seq);
static BOOL FrameFunc_EventResultShare(PKTHLN_PTR work, u8 *seq);
static BOOL FrameFunc_ParentShareRsltData(PKTHLN_PTR work, u8 *seq);
static BOOL FrameFunc_EventResultMake(PKTHLN_PTR work, u8 *seq);
static BOOL FrameFunc_EventEnd(PKTHLN_PTR work, u8 *seq);
static BOOL FrameFunc_EventNext(PKTHLN_PTR work, u8 *seq);
static BOOL FrameFunc_End(PKTHLN_PTR work, u8 *seq);
static BOOL FrameFunc_CallBackWait(PKTHLN_PTR work, u8 *seq);

static BOOL AddUpParentOnly( PKTHLN_PTR work );
static void SetResultTmpData(PKTHLN_PTR work, const u8 inEvt);
static void SetSaveData(PKTHLN_PTR work);

static BOOL FrameFuncResultSet(PKTHLN_PTR work, u8 *seq);
static BOOL FrameFuncResultInit(PKTHLN_PTR work, u8 *seq);
static BOOL FrameFuncResultMain(PKTHLN_PTR work, u8 *seq);
static BOOL FrameFuncResultEnd(PKTHLN_PTR work, u8 *seq);

static BOOL FrameFuncEndingSet(PKTHLN_PTR work, u8 *seq);
static BOOL FrameFuncEndingInit(PKTHLN_PTR work, u8 *seq);
static BOOL FrameFuncEndingMain(PKTHLN_PTR work, u8 *seq);
static BOOL FrameFunc_SendMyJuiceDat(PKTHLN_PTR work, u8 *seq);
static BOOL FrameFunc_SetJuiceDatToSv(PKTHLN_PTR work, u8 *seq);
///static BOOL FrameFunc_ParentShareJcData(PKTHLN_PTR work, u8 *seq);
static BOOL FrameFuncEndingEnd(PKTHLN_PTR work, u8 *seq);

static BOOL FrameFunc_SendEvtActData(PKTHLN_PTR work, u8 *seq);
static BOOL FrameFunc_ParentShareActData(PKTHLN_PTR work, u8 *seq);

static void DecideEvt(const POKETHLON_HEADER *inHeader, const u8 inEvtMax, u8 *outEvt);

static void PosMarkerTask(TCB_PTR tcb, void* work);

static void StartPenAnm(PKTHLN_PTR work);
static BOOL CheckPenAnmEnd(PKTHLN_PTR work);

static void AddActionPoint(	const ACTION_ADD_TYPE inAddType, const u8 inAddVal,
							PKTHLN_POKE_RSLT *outRslt	);
static BOOL CheckNewRecord(PKTHLN_PTR work);

//セーブへの反映関連
static void MakeCourseData(PKTHLN_PTR work, PKTH_COURSE * outCourseData);
static void MakeEvtDataAlone(PKTHLN_PTR work, PKTH_EVT_DATA *outData);
static void MakeEvtDataComm(PKTHLN_PTR work, PKTH_COMM_EVT_DATA *outCommData);
static void MakeBestRecScore(PKTHLN_PTR work, const PKTH_EVT_DATA *inEvtData, u16 *outData);
static void SetWinPoke(PKTHLN_PTR work);

/**
static void BableSortAlone( const COMP_MODE inCompMode,
							PKTH_EVT_RCMS *inRcms,
							PKTH_EVT_DATA *ioData );
*/
static void SortData(const COMP_MODE inCompMode, const SORT_DATA *inSortDat, SORT_DATA *ioSortDatAry);
static void WriteBestFiveDataAlone(	PKTHLN_PTR work, PKTH_EVT_DATA *evt_data,
									const SORT_DATA *inSortDatAry	);
static void WriteBestFiveDataComm(	PKTHLN_PTR work, PKTH_COMM_EVT_DATA *comm_evt_data,
									const SORT_DATA *inSortDatAry	);
/*
 * static void BableSortComm(	const COMP_MODE inCompMode,
							PKTH_TR_DATA *inTrData, PKTH_EVT_RCMS *inRcms,
							PKTH_COMM_EVT_DATA *ioData	);
*/
static BOOL CompVal(const int inBase, const int inTarget, const COMP_MODE inCompMode);
static BOOL CompValCore(const int inBase, const int inTarget, const COMP_MODE inCompMode);
static void MakeRankData(PKTHLN_PTR work, PKTH_RNK_DATA *outRankData);
static void AddValLimitCheck( const u32 inVal, const u32 inLimit, u32 *ioBuf );
static void SetMedal(PKTHLN_PTR work);
static void SetMyPokeMedal(PKTHLN_PTR work, const u8 inMask);
static BOOL CheckAloneCrsWin(const PKTH_COURSE * inCourseData);
static BOOL	CheckOnePokeAllMedal(PKTHLN_PTR work);
static BOOL	CheckDefaultRecordUpdate(PKTHLN_PTR work);

static void MakeNpcCode(const u8 inNpcNum, const CRS_ID inCrsID, const BOOL inAllStar, u8 *outNpcCode);

//通信同期
extern PTH_RC PE_CommWait_InitFunc(PKTHLN_PTR work, void *pParam);
extern BOOL PE_CommWait_DrawFunc(PKTHLN_PTR work, void *pparam);
extern BOOL PE_CommWait_EndFunc(PKTHLN_PTR work, void *pParam);
//開会式イベント
extern PTH_RC PE_OPENING_InitFunc(PKTHLN_PTR work, void *param);
extern BOOL PE_OPENING_DrawFunc(PKTHLN_PTR work, void *param);
extern BOOL PE_OPENING_EndFunc(PKTHLN_PTR work, void *param);
//競技タイトルコール
extern PTH_RC EvtStart_InitFunc(PKTHLN_PTR work, void *param);
extern BOOL EvtStart_DrawFunc(PKTHLN_PTR work, void *param);
extern BOOL EvtStart_EndFunc(PKTHLN_PTR work, void *param);
#if 0
//テストイベント
extern PTH_RC PE_TEST_InitFunc(PKTHLN_PTR work, void *param);
extern BOOL PE_TEST_DrawFunc(PKTHLN_PTR work, void *param);
extern BOOL PE_TEST_EndFunc(PKTHLN_PTR work, void *param);
#endif
//障害物走
extern PTH_RC PE_DASH_InitFunc(PKTHLN_PTR work, void *param);
extern BOOL PE_DASH_DrawFunc(PKTHLN_PTR work, void *param);
extern BOOL PE_DASH_ResultFunc(PKTHLN_PTR work, void *pParam);
extern BOOL PE_DASH_EndFunc(PKTHLN_PTR work, void *param);

//おしくらまんじゅう
extern PTH_RC PE_PUSH_InitFunc(PKTHLN_PTR work, void *param);
extern BOOL PE_PUSH_DrawFunc(PKTHLN_PTR work, void *param);
extern BOOL PE_PUSH_ResultFunc(PKTHLN_PTR work, void *pParam);
extern BOOL PE_PUSH_EndFunc(PKTHLN_PTR work, void *param);
//ジャンプ
extern PTH_RC PE_JUMP_InitFunc(PKTHLN_PTR work, void *param);
extern BOOL PE_JUMP_DrawFunc(PKTHLN_PTR work, void *param);
extern BOOL PE_JUMP_ResultFunc(PKTHLN_PTR work, void *pParam);
extern BOOL PE_JUMP_EndFunc(PKTHLN_PTR work, void *param);
#if 0
//2画面テスト
extern PTH_RC PE_DBL_InitFunc(PKTHLN_PTR work, void *param);
extern BOOL PE_DBL_DrawFunc(PKTHLN_PTR work, void *param);
extern BOOL PE_DBL_ResultFunc(PKTHLN_PTR work, void *pParam);
extern BOOL PE_DBL_EndFunc(PKTHLN_PTR work, void *param);
#endif
//ハードル
extern PTH_RC PE_HURDLE_InitFunc(PKTHLN_PTR work, void *param);
extern BOOL PE_HURDLE_DrawFunc(PKTHLN_PTR work, void *param);
extern BOOL PE_HURDLE_ResultFunc(PKTHLN_PTR work, void *pParam);
extern BOOL PE_HURDLE_EndFunc(PKTHLN_PTR work, void *param);
//マラソン
extern PTH_RC PE_RUN_InitFunc(PKTHLN_PTR work, void *param);
extern BOOL PE_RUN_DrawFunc(PKTHLN_PTR work, void *param);
extern BOOL PE_RUN_ResultFunc(PKTHLN_PTR work, void *pParam);
extern BOOL PE_RUN_EndFunc(PKTHLN_PTR work, void *param);
//玉投げ
extern PTH_RC PE_THROW_InitFunc(PKTHLN_PTR work, void *param);
extern BOOL PE_THROW_DrawFunc(PKTHLN_PTR work, void *param);
extern BOOL PE_THROW_ResultFunc(PKTHLN_PTR work, void *pParam);
extern BOOL PE_THROW_EndFunc(PKTHLN_PTR work, void *param);
//フラッグ
extern PTH_RC PE_STL_InitFunc(PKTHLN_PTR work, void *param);
extern BOOL PE_STL_DrawFunc(PKTHLN_PTR work, void *param);
extern BOOL PE_STL_ResultFunc(PKTHLN_PTR work, void *pParam);
extern BOOL PE_STL_EndFunc(PKTHLN_PTR work, void *param);
//かわらわり
extern PTH_RC PE_BREAK_InitFunc(PKTHLN_PTR work, void* pParam);
extern BOOL PE_BREAK_DrawFunc(PKTHLN_PTR work, void* pParam);
extern BOOL PE_BREAK_ResultFunc(PKTHLN_PTR work, void* pParam);
extern BOOL PE_BREAK_EndFunc(PKTHLN_PTR work, void* pParam);
//UFOキャッチ
extern PTH_RC PE_CATCH_InitFunc(PKTHLN_PTR work, void* pParam);
extern BOOL PE_CATCH_DrawFunc(PKTHLN_PTR work, void* pParam);
extern BOOL PE_CATCH_ResultFunc(PKTHLN_PTR work, void* pParam);
extern BOOL PE_CATCH_EndFunc(PKTHLN_PTR work, void* pParam);
//シュート
extern PTH_RC PE_SHOT_InitFunc(PKTHLN_PTR work, void *param);
extern BOOL PE_SHOT_DrawFunc(PKTHLN_PTR work, void *param);
extern BOOL PE_SHOT_ResultFunc(PKTHLN_PTR work, void *pParam);
extern BOOL PE_SHOT_EndFunc(PKTHLN_PTR work, void *param);
//レスリング
extern PTH_RC PE_DROP_InitFunc(PKTHLN_PTR work, void* pParam);
extern BOOL PE_DROP_DrawFunc(PKTHLN_PTR work, void* pParam);
extern BOOL PE_DROP_ResultFunc(PKTHLN_PTR work, void* pParam);
extern BOOL PE_DROP_EndFunc(PKTHLN_PTR work, void* pParam);

//結果発表
extern PTH_RC PE_RESULT_InitFunc(PKTHLN_PTR work, void *param);
extern BOOL PE_RESULT_DrawFunc(PKTHLN_PTR work, void *param);
extern BOOL PE_RESULT_EndFunc(PKTHLN_PTR work, void *param);
//閉会式イベント
extern PTH_RC PE_ENDING_InitFunc(PKTHLN_PTR work, void *param);
extern BOOL PE_ENDING_DrawFunc(PKTHLN_PTR work, void *param);
extern BOOL PE_ENDING_EndFunc(PKTHLN_PTR work, void *param);

#ifdef PM_DEBUG
static void PrintActPoint(PKTHLN_PTR work);
static void PrintLocalActPoint(PKTHLN_PTR work);
#endif

static const POKETHLON_FUNC_TBL PE_CommWaitFuncTbl = {
	PE_CommWait_InitFunc,
	PE_CommWait_DrawFunc,
	NULL,
	PE_CommWait_EndFunc,
	FALSE,
};

static const POKETHLON_FUNC_TBL PE_OpeningFuncTbl = {
	PE_OPENING_InitFunc,
	PE_OPENING_DrawFunc,
	NULL,
	PE_OPENING_EndFunc,
	FALSE,
};

static const POKETHLON_FUNC_TBL PE_EvtStartFuncTbl = {
	EvtStart_InitFunc,
	EvtStart_DrawFunc,
	NULL,
	EvtStart_EndFunc,
	FALSE,
};
#if 0
static const POKETHLON_FUNC_TBL PE_DummyFuncTbl = {
	PE_TEST_InitFunc,
	PE_TEST_DrawFunc,
	NULL,
	PE_TEST_EndFunc,
	FALSE,
};
#endif
static const POKETHLON_FUNC_TBL PE_DashFuncTbl = {
	PE_DASH_InitFunc,
	PE_DASH_DrawFunc,
	PE_DASH_ResultFunc,
	PE_DASH_EndFunc,
	TRUE,
};

static const POKETHLON_FUNC_TBL PE_PushFuncTbl = {
	PE_PUSH_InitFunc,
	PE_PUSH_DrawFunc,
	PE_PUSH_ResultFunc,
	PE_PUSH_EndFunc,
	FALSE,
};

static const POKETHLON_FUNC_TBL PE_JumpFuncTbl = {
	PE_JUMP_InitFunc,
	PE_JUMP_DrawFunc,
	PE_JUMP_ResultFunc,
	PE_JUMP_EndFunc,
	TRUE,
};
#if 0
static const POKETHLON_FUNC_TBL PE_DblFuncTbl = {
	PE_DBL_InitFunc,
	PE_DBL_DrawFunc,
	PE_DBL_ResultFunc,
	PE_DBL_EndFunc,
	FALSE,
};
#endif

static const POKETHLON_FUNC_TBL PE_HurdleFuncTbl = {
	PE_HURDLE_InitFunc,
	PE_HURDLE_DrawFunc,
	PE_HURDLE_ResultFunc,
	PE_HURDLE_EndFunc,
	TRUE,
};

static const POKETHLON_FUNC_TBL PE_RunFuncTbl = {
	PE_RUN_InitFunc,
	PE_RUN_DrawFunc,
	PE_RUN_ResultFunc,
	PE_RUN_EndFunc,
	FALSE,
};

static const POKETHLON_FUNC_TBL PE_ThrowFuncTbl = {
	PE_THROW_InitFunc,
	PE_THROW_DrawFunc,
	PE_THROW_ResultFunc,
	PE_THROW_EndFunc,
	FALSE,
};

static const POKETHLON_FUNC_TBL PE_StlFuncTbl = {
	PE_STL_InitFunc,
	PE_STL_DrawFunc,
	PE_STL_ResultFunc,
	PE_STL_EndFunc,
	FALSE,
};

static const POKETHLON_FUNC_TBL PE_BreakFuncTbl  = {
	PE_BREAK_InitFunc,
	PE_BREAK_DrawFunc,
	PE_BREAK_ResultFunc,
	PE_BREAK_EndFunc,
	TRUE,
};

static const POKETHLON_FUNC_TBL PE_CatchFuncTbl = {
	PE_CATCH_InitFunc,
	PE_CATCH_DrawFunc,
	PE_CATCH_ResultFunc,
	PE_CATCH_EndFunc,
	FALSE,
};

static const POKETHLON_FUNC_TBL PE_ShotFuncTbl = {
	PE_SHOT_InitFunc,
	PE_SHOT_DrawFunc,
	PE_SHOT_ResultFunc,
	PE_SHOT_EndFunc,
	FALSE,
};

static const POKETHLON_FUNC_TBL PE_DropFuncTbl = {
	PE_DROP_InitFunc,
	PE_DROP_DrawFunc,
	PE_DROP_ResultFunc,
	PE_DROP_EndFunc,
	FALSE,
};

static const POKETHLON_FUNC_TBL PE_ResultFuncTbl = {
	PE_RESULT_InitFunc,
	PE_RESULT_DrawFunc,
	NULL,
	PE_RESULT_EndFunc,
	FALSE,
};

static const POKETHLON_FUNC_TBL PE_EndingFuncTbl = {
	PE_ENDING_InitFunc,
	PE_ENDING_DrawFunc,
	NULL,
	PE_ENDING_EndFunc,
	FALSE,
};

//フレームワークファンクションテーブル
static const PKTHLN_FUNC FrameFuncTbl[] = {
	FrameFunc_ShareEventNo,
	FrameFunc_PokemonSelect,

	FrameFunc_WaitPokeSel,

	FrameFunc_PokemonEntry,
	FrameFunc_ParentSharePokemon,
	FrameFunc_SetMyStatus,
	FrameFunc_SendMyRankData,
///	FrameFunc_ParentShareRankData,

	FrameFuncOpeningSet,
	FrameFuncOpeningInit,
	FrameFuncOpeningMain,
	FrameFuncOpeningEnd,

	FrameFuncEvtCallSet,
	FrameFuncEvtCallInit,
	FrameFuncEvtCallMain,
	FrameFuncEvtCallEnd,

	FrameFunc_EventSet,
	FrameFunc_EventInit,
///	FrameFunc_ChangeEventCommand,
	FrameFunc_EventShareData,
	FrameFunc_EventMain,
	FrameFunc_EventRsltShareStart,
	FrameFunc_EventResultShare,
	FrameFunc_ParentShareRsltData,

	FrameFunc_EventResultMake,
	FrameFunc_EventEnd,
	FrameFunc_EventNext,

	FrameFuncResultSet,
	FrameFuncResultInit,
	FrameFuncResultMain,
	FrameFuncResultEnd,

	FrameFunc_SendEvtActData,
	FrameFunc_ParentShareActData,

	FrameFuncEndingSet,
	FrameFuncEndingInit,
	FrameFuncEndingMain,
	FrameFuncEndingEnd,

	FrameFunc_SendMyJuiceDat,
	FrameFunc_SetJuiceDatToSv,
///	FrameFunc_ParentShareJcData,

	FrameFunc_End,
	FrameFunc_CallBackWait,
};

//競技毎のレコードの昇順判定
const u8 SortComp[PKTHLN_EVT_MAX] = {
	COMP_SMALL,	//ハードル
	COMP_LARGE, //フラッグ
	COMP_LARGE,	//サークル
	COMP_LARGE,	//カワラ
	COMP_LARGE,	//ＵＦＯ
	COMP_LARGE,	//ジャンプ
	COMP_LARGE,	//マラソン
	COMP_LARGE,	//レスリング
	COMP_LARGE,	//玉投げ
	COMP_LARGE,	//シュート
};

//比較デフォルトレコード
const u16 DefautlRec[PKTHLN_EVT_MAX] = {
	PKTH_DEF_REC_DASH *30,		//ハードル	「びょう」をシンクに変換
	PKTH_DEF_REC_STEAL,			//フラッグ
	PKTH_DEF_REC_PUSH,			//サークル
	PKTH_DEF_REC_BREAK,			//カワラ
	PKTH_DEF_REC_CATCH,			//ＵＦＯ
	PKTH_DEF_REC_JUMP,			//ジャンプ
	PKTH_DEF_REC_RUN * 1024,	//マラソン	「しゅう」を　きょりに変換
	PKTH_DEF_REC_DROP,			//レスリング
	PKTH_DEF_REC_THROW,			//玉投げ
	PKTH_DEF_REC_SHOT,			//シュート
};

extern PKTHLN_FUNC CommWaitFuncTbl[];
extern PKTHLN_FUNC OpeningFuncTbl[];
extern PKTHLN_FUNC EvtStartFuncTbl[];
///extern PKTHLN_FUNC TestFuncTbl[];
extern PKTHLN_FUNC EndingFuncTbl[];
extern PKTHLN_FUNC DashFuncTbl[];
extern PKTHLN_FUNC PushFuncTbl[];
extern PKTHLN_FUNC JumpFuncTbl[];
#if 0
extern PKTHLN_FUNC DblFuncTbl[];
#endif
extern PKTHLN_FUNC HurdleFuncTbl[];
extern PKTHLN_FUNC RunFuncTbl[];
extern PKTHLN_FUNC ThrowFuncTbl[];
extern PKTHLN_FUNC StlFuncTbl[];
extern PKTHLN_FUNC BreakFuncTbl[];
extern PKTHLN_FUNC CatchFuncTbl[];
extern PKTHLN_FUNC ShotFuncTbl[];
extern PKTHLN_FUNC DropFuncTbl[];
extern PKTHLN_FUNC ResultFuncTbl[];

//種目テーブル(競技コード順)
static const PKTHLN_FUNC *EventTable[] = {
	HurdleFuncTbl,		//ハードル
	StlFuncTbl,			//フラッグ
	PushFuncTbl,		//サークル
	BreakFuncTbl,		//カワラ
	CatchFuncTbl,		//UFO
	JumpFuncTbl,		//トランポリン
	RunFuncTbl,			//マラソン
	DropFuncTbl,		//レスリング
	ThrowFuncTbl,		//玉投げ
	ShotFuncTbl,		//シュート
};

//種目別プロシージャテーブル(競技コード順)
static const POKETHLON_FUNC_TBL *ProcFuncTbl [] = {
	&PE_HurdleFuncTbl,	//ハードル
	&PE_StlFuncTbl,	//フラッグ
	&PE_PushFuncTbl,	//サークル
	&PE_BreakFuncTbl,	//カワラ
	&PE_CatchFuncTbl,	//UFO
	&PE_JumpFuncTbl,	//トランポリン
	&PE_RunFuncTbl,		//マラソン
	&PE_DropFuncTbl,	//レスリング
	&PE_ThrowFuncTbl,	//玉投げ
	&PE_ShotFuncTbl,	//シュート
};

//コース・競技　テーブル
#include "pkthln_crs_tbl.dat"

//マスターコーステーブル
static const u8 mas_crs_evt_tbl[MAS_NO_NUM][PKTHLN_EVT_MAX_COMM] = {
	{ PKTHLN_EVT_CATCH,PKTHLN_EVT_PUSH,PKTHLN_EVT_SHOT,PKTHLN_EVT_DROP },
	{ PKTHLN_EVT_DROP,PKTHLN_EVT_PUSH,PKTHLN_EVT_BREAK,PKTHLN_EVT_THROW },
	{ PKTHLN_EVT_JUMP,PKTHLN_EVT_DASH,PKTHLN_EVT_SHOT,PKTHLN_EVT_DROP },
	{ PKTHLN_EVT_BREAK,PKTHLN_EVT_RUN,PKTHLN_EVT_THROW,PKTHLN_EVT_JUMP },
	{ PKTHLN_EVT_THROW,PKTHLN_EVT_JUMP,PKTHLN_EVT_BREAK,PKTHLN_EVT_DASH },
	{ PKTHLN_EVT_STEAL,PKTHLN_EVT_PUSH,PKTHLN_EVT_SHOT,PKTHLN_EVT_CATCH },
	{ PKTHLN_EVT_PUSH,PKTHLN_EVT_RUN,PKTHLN_EVT_JUMP,PKTHLN_EVT_BREAK },
	{ PKTHLN_EVT_DASH,PKTHLN_EVT_DROP,PKTHLN_EVT_BREAK,PKTHLN_EVT_SHOT },
	{ PKTHLN_EVT_SHOT,PKTHLN_EVT_THROW,PKTHLN_EVT_CATCH,PKTHLN_EVT_STEAL },
	{ PKTHLN_EVT_RUN,PKTHLN_EVT_BREAK,PKTHLN_EVT_DROP,PKTHLN_EVT_DASH },
};

#ifdef PM_DEBUG
#ifdef DEBUG_NPC_POKE
static const u16 DebugNpcMonsNo[3][3] = {
	{MONSNO_REZIKINGU,MONSNO_REZIKINGU,MONSNO_REZIKINGU},
	{MONSNO_REZIKINGU,MONSNO_REZIKINGU,MONSNO_REZIKINGU},
	{MONSNO_GURAADON,MONSNO_REKKUUZA,MONSNO_KAIOOGA},
};
#endif
#endif

//想定されるアプリケーション
//開会式
//タイトルコール
//競技
//閉会式

///extern const CommPacketTbl* PKTHLN_Test_GetCommCommandTbl( void );
///extern int PKTHLN_Test_GetCommCommandTblNum( void );

//--------------------------------------------------------------------------------------------
/**
 * ダミー初期化関数
 *
 * @param	work			ワーク
 * @param	param			パラメータ
 *
 * @return	PTH_RC			リターンコード
 */
//--------------------------------------------------------------------------------------------
static PTH_RC DummyInitFunc(PKTHLN_PTR work, void *param)
{
	return PTH_RC_END;
}

//--------------------------------------------------------------------------------------------
/**
 * ダミー関数
 *
 * @param	work			ワーク
 * @param	param			パラメータ
 *
 * @return	BOOL			TRUE:終了	FALSE:継続
 */
//--------------------------------------------------------------------------------------------
static BOOL DummyFunc(PKTHLN_PTR work, void *param)
{
	return TRUE;
}

//--------------------------------------------------------------------------------------------
/**
 * ポケスロンメインフレームプロセス	初期化処理
 *
 * @param	proc			プロセス
 * @param	seq				シーケンス
 *
 * @return	PROC_RESULT		プロセスリターンコード
 */
//--------------------------------------------------------------------------------------------
PROC_RESULT PTFrame_Init(PROC * proc, int * seq)
{
	POKETHLON_WORK *work;
#ifdef PM_DEBUG
	SysHeap = sys_GetHeapFreeSize(HEAPID_BASE_SYSTEM);
	SaveHeap = sys_GetHeapFreeSize(HEAPID_BASE_SAVE);
	AppHeap = sys_GetHeapFreeSize(HEAPID_BASE_APP);
#endif
	//ヒープ作成
	sys_CreateHeap( HEAPID_BASE_APP, HEAPID_POKETHLON, POKETHLON_MEM_SIZE );

	//ポケスロンワークをアロケーションする
	work = PROC_AllocWork(proc, sizeof(POKETHLON_WORK), HEAPID_POKETHLON);
///	InitWork();
	//確保領域のクリーン
	MI_CpuClear8( work, sizeof(POKETHLON_WORK));

	//ヒープＩＤ記憶
	work->HeapID = HEAPID_POKETHLON;

	//上位ワークの情報をポケスロンワークに格納する
	work->LinkData.Header = PROC_GetParentWork( proc );

	OS_Printf("オールスターフラグ:%d\n",work->LinkData.Header->AllStar);

	//ポケモン選択Procの作成
	{
		// オーバーレイID宣言
		FS_EXTERN_OVERLAY( pokethlon_pk_select );
		// プロセス定義データ
		const PROC_DATA PokeSelectProcData = {
			PKTHLN_PokeSelect_Init,
			PKTHLN_PokeSelect_Main,
			PKTHLN_PokeSelect_End,
			FS_OVERLAY_ID(pokethlon_pk_select)
//			NO_OVERLAY_ID
		};
		work->PokeSelectProc = PROC_Create(&PokeSelectProcData, &work->LinkData, HEAPID_POKETHLON);
	}

	work->FuncTbl = NULL;

	{
		int comm_flg;
		if (work->LinkData.Header->GameType == PKTHLN_GAME_COMM){
			comm_flg = PKTHLN_COMM_PACK_COMM;
			work->PlayerNum = CommGetConnectNum();		//参加プレーヤー人数2〜4
			work->EventMax = PKTHLN_EVT_MAX_COMM;			//競技数
		}else{
			comm_flg = PKTHLN_COMM_PACK_ONE;
			work->PlayerNum = 1;						//参加プレーヤー人数1
			work->EventMax = PKTHLN_EVT_MAX_ALONE;			//競技数
		}
		//通信パッケージポインタ作成
		work->CommPackPtr = PKTHLN_CommPack_CommandInitialize(
								PKTHLN_GetCommCommandTbl(),
								PKTHLN_GetCommCommandTblNum(),
								work, comm_flg, work->HeapID );
	}

	//フレームシーケンスデータ初期化
	InitSeqData(&FrameFuncTbl[0], &work->FrameSeq);
	work->FrameSeq.TblIdx = FRAME_SEQ_SHARE_EVENT;

	//フレームシーケンスをアクティブシーケンスにセット
	work->SeqCnt.ActiveSeqData = &work->FrameSeq;
	work->SeqCnt.ChgReqFlg = 0;

	//マイステータスセット
	SetMyStatus(work);

	//競技結果格納場所のアロケート
	work->Result = RSLT_Alloc(HEAPID_POKETHLON);

	//メッセージフラグ関連設定
	if(work->LinkData.Header->GameType != PKTHLN_GAME_COMM){
		//非通信時
		MsgPrintSkipFlagSet(MSG_SKIP_ON);
		MsgPrintAutoFlagSet(MSG_AUTO_OFF);
		MsgPrintTouchPanelFlagSet(MSG_TP_ON);
	}
	else{
		//通信時
		MsgPrintSkipFlagSet(MSG_SKIP_OFF);
		MsgPrintAutoFlagSet(MSG_AUTO_ON);
		MsgPrintTouchPanelFlagSet(MSG_TP_OFF);
	}

	//描画を禁止
	PTFrame_SetDraw(work, FALSE);

	PTFrame_SetSubSeq(work, 0);
	return PROC_RES_FINISH;
}

//--------------------------------------------------------------------------------------------
/**
 * ポケスロンメインフレームプロセス	メイン処理
 *
 * @param	proc			プロセス
 * @param	seq				シーケンス
 *
 * @return	PROC_RESULT		プロセスリターンコード
 */
//--------------------------------------------------------------------------------------------
PROC_RESULT PTFrame_Main(PROC * proc, int * seq)
{
	POKETHLON_WORK *work;
	SEQ_CONTROLER *cnt_ptr;

	work = PROC_GetWork(proc);
	cnt_ptr = &work->SeqCnt;

	//時間カウント(開会式が始まったらカウント開始)
	if (work->OpeningStart){
		work->FrameCount++;
		if (work->FrameCount >= 30*60){
			//1分経過
			if (work->PlayTime < PLAY_TIME_MAX){
				work->PlayTime++;
			}
			work->FrameCount = 0;
		}
	}

	switch(cnt_ptr->MainSeq){
	case PKTHLN_FRM_SEQ_MAIN:
		//ポケスロンメイン呼び出し
		if ( PokethlonMain(work) ){
			return PROC_RES_FINISH;
		}

		// アクティブなシーケンスデータのリクエストシーケンスを設定
		if( cnt_ptr->ChgReqFlg ){
			SEQ_DATA *seq_data;
			//現在アクティブになっているシーケンスデータを取得
			seq_data = cnt_ptr->ActiveSeqData;
			//リクエストを反映
			seq_data->TblIdx = seq_data->TblIdxReq;
			OS_Printf("TblIdx = %d\n",seq_data->TblIdx);
			//サブシーケンサリセット
			seq_data->SubSeq = 0;
			//シーケンス変更フラグ解除
			cnt_ptr->ChgReqFlg = 0;
		}

		//通信同期チェック
		if(cnt_ptr->SynchroID != SYNCHROID_NONE){
			//通信同期に入る
			if (cnt_ptr->SynchroID == PKTHLN_SYNC_ID_EVENT_END_WAIT){
				cnt_ptr->MainSeq = PKTHLN_FRM_SEQ_EVT_END_SYNCSTART;
			}else{
				cnt_ptr->MainSeq = PKTHLN_FRM_SEQ_SYNCSTART;
			}
		}
		break;
	case PKTHLN_FRM_SEQ_SYNCSTART:
		CommTimingSyncStart(cnt_ptr->SynchroID);
		cnt_ptr->MainSeq = PKTHLN_FRM_SEQ_SYNCWAIT;
		/*NONE_BREAK*/
	case PKTHLN_FRM_SEQ_SYNCWAIT:
		OS_Printf("通信同期中\n");
		if(!CommIsTimingSync(cnt_ptr->SynchroID)){
			break;
		}
		//通信同期終了&次のシーケンスへ
		cnt_ptr->MainSeq = PKTHLN_FRM_SEQ_MAIN;
		cnt_ptr->SynchroID = SYNCHROID_NONE;
		break;
	case PKTHLN_FRM_SEQ_EVT_END_SYNCSTART:
		GF_ASSERT_MSG(cnt_ptr->SynchroID == PKTHLN_SYNC_ID_EVENT_END_WAIT,"SyncID:%d\n",cnt_ptr->SynchroID);
		CommTimingSyncStart(cnt_ptr->SynchroID);
		cnt_ptr->MainSeq = PKTHLN_FRM_SEQ_EVT_END_SYNCWAIT;
		/*NONE_BREAK*/
	case PKTHLN_FRM_SEQ_EVT_END_SYNCWAIT:
		OS_Printf("競技終了通信同期中 %d\n",cnt_ptr->SynchroID);
		if(!CommIsTimingSync(cnt_ptr->SynchroID)){
			if ( PTFrameGetCurrentID(work) == COMM_PARENT_ID ){		//親
				PKTHLN_CommPack_CommSendData( COMM_PKTHLN_EVT_CMN_DATA, &work->EvtComCmnData.SendShareData,
					CommPkthlnGetEvtCmnDataSize(), work->CommPackPtr );
				{
					//親データは直接レシーバにセット
					PTHLN_COMM_DATA *child;
					PTHLN_COMM_DATA *child_rec;
					child_rec = PKTHLN_CommPack_GetData(&work->EvtComCmnData.ReciveData[0]);
					child = PKTHLN_CommPack_GetData(&work->EvtComCmnData.SendData);
					(*child_rec) = (*child);
				}
			}
			//子機は同期が取れるまで何もしない
			break;
		}
		//通信同期終了&次のシーケンスへ
		cnt_ptr->MainSeq = PKTHLN_FRM_SEQ_MAIN;
		cnt_ptr->SynchroID = SYNCHROID_NONE;
		break;
	}

	EventDraw(work);

	return PROC_RES_CONTINUE;
}

//--------------------------------------------------------------------------------------------
/**
 * ポケスロンメインフレームプロセス	終了処理
 *
 * @param	proc			プロセス
 * @param	seq				シーケンス
 *
 * @return	PROC_RESULT		プロセスリターンコード
 */
//--------------------------------------------------------------------------------------------
PROC_RESULT PTFrame_End(PROC * proc, int * seq)
{
	int i;
	POKETHLON_WORK *work;
	work = PROC_GetWork(proc);

	GF_ASSERT(sys_CheckHeapSafe( HEAPID_POKETHLON));

	if (!work->LinkData.Header->RetExit){
		//ジュースメモリ解放
		sys_FreeMemoryEz(work->JuiceData);
		sys_FreeMemoryEz(work->AllJuiceData);
	}

	//プレイ時間を加算
	{
		PKTHLN_SV_DATA_PTR save = PkthlnSv_GetSaveData(work->LinkData.Header->SaveData);
		PKTH_RNK_DATA * rank_data = PkthlnSv_GetRnkData(save);
		AddValLimitCheck( work->PlayTime, PLAY_TIME_MAX, &rank_data->PlayMinute );
		OS_Printf("プレイ時間：%d分 トータルプレイ時間：%d分\n",work->PlayTime, rank_data->PlayMinute);
	}

	//メッセージプリント設定をリセット
	MsgPrintSkipFlagSet(MSG_SKIP_OFF);
	MsgPrintAutoFlagSet(MSG_AUTO_OFF);
	MsgPrintTouchPanelFlagSet(MSG_TP_OFF);

	//競技結果格納場所の解放
	RSLT_Free(work->Result);
OS_Printf("リザルト解放\n");
	//マイステータス解放
	sys_FreeMemoryEz(work->MyStatus);
OS_Printf("マイステ解放\n");

/**
	for(i=0;i<ENTRY_MEMBER_NUM_MAX;i++){
		sys_FreeMemoryEz(work->MyStatus[i]);
	}
*/
	//通信パッケージ解放
	PKTHLN_CommPack_CommDelete( work->CommPackPtr );
OS_Printf("パッケージ解放\n");
	//ワーク解放
	PROC_FreeWork(proc);
OS_Printf("ワーク解放\n");
	//ヒープ解放
	sys_DeleteHeap( HEAPID_POKETHLON );

#ifdef PM_DEBUG
	//ヒープ調べる
	if(SysHeap != sys_GetHeapFreeSize(HEAPID_BASE_SYSTEM)){
		GF_ASSERT_MSG(0, "SYS_HEAP SIZE %d < %d\n",
						SysHeap, sys_GetHeapFreeSize(HEAPID_BASE_SYSTEM));
	}
	if(SaveHeap != sys_GetHeapFreeSize(HEAPID_BASE_SAVE)){
		GF_ASSERT_MSG(0, "SAVE_HEAP SIZE %d < %d\n",
						SaveHeap, sys_GetHeapFreeSize(HEAPID_BASE_SAVE));
	}
	if(AppHeap != sys_GetHeapFreeSize(HEAPID_BASE_APP)){
		GF_ASSERT_MSG(0, "DEBUG_HEAP SIZE %d < %d\n",
						AppHeap, sys_GetHeapFreeSize(HEAPID_BASE_APP));
	}
#endif

	return PROC_RES_FINISH;
}

//--------------------------------------------------------------------------------------------
/**
 * ポケスロンメイン
 *
 * @param	work			ポケスロンワーク
 *
 * @return	BOOL			TRUE:処理終了 FALSE:処理継続
 */
//--------------------------------------------------------------------------------------------
static BOOL PokethlonMain(PKTHLN_PTR work)
{
	//シーケンスの実行
	PKTHLN_FUNC func = work->FrameSeq.FuncTbl[work->FrameSeq.TblIdx];

	if ( func(work, &work->FrameSeq.SubSeq) ){
		return TRUE;
	}
	return FALSE;
}

//--------------------------------------------------------------------------------------------
/**
 * ポケスロンメインフレームプロセス	初期化
 *
 * @param	work		ポケスロンワークポインタ
 *
 * @return	BOOL		TRUE:処理終了 FALSE:処理継続
 */
//--------------------------------------------------------------------------------------------
static BOOL FuncInit(PKTHLN_PTR work)
{
	do{
		PTH_RC rc;
		rc = work->FuncTbl->InitFunc(work, NULL);
		if (rc == PTH_RC_END){
			return TRUE;
		}
		else if (rc == PTH_RC_LOOP){
			//一度メインフレームに処理を戻す
			break;
		}
	}while(work->LinkData.Header->GameType == PKTHLN_GAME_ALONE); //通信中ではないなら、処理を続ける

	return FALSE;
}

//--------------------------------------------------------------------------------------------
/**
 * シーケンスデータの初期化
 *
 * @param	inFuncTbl		ファンクションテーブル
 * @param	outSeqData		シーケンスデータ
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void InitSeqData(const PKTHLN_FUNC *inFuncTbl, SEQ_DATA *outSeqData)
{
	outSeqData->FuncTbl = inFuncTbl;
	outSeqData->TblSize = sizeof(inFuncTbl)/sizeof(PKTHLN_FUNC);
	outSeqData->SubSeq = 0;
	outSeqData->TblIdx = 0;
	outSeqData->TblIdxReq = 0;
	OS_Printf("ファンクションテーブルサイズ：%d\n", outSeqData->TblSize);
}

//--------------------------------------------------------------------------------------------
/**
 * マイステータスセット	通信人数によるメモリのずれが嫌なので、4つ分のメモリ確保はする
 *
 * @param	work			ポケスロンワーク
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void SetMyStatus(PKTHLN_PTR work)
{
	int i;
	MYSTATUS * my;
	work->MyStatus = sys_AllocMemory( work->HeapID, MyStatus_GetWorkSize()*ENTRY_MEMBER_NUM_MAX );
	for(i=0;i<ENTRY_MEMBER_NUM_MAX;i++){
///		work->MyStatus[i] = MyStatus_AllocWork(work->HeapID);
		my = GetMyStatus(work->MyStatus, i);
		MyStatus_Init(my);
	}

	//通信・非通信で分岐
	if (work->LinkData.Header->GameType == PKTHLN_GAME_ALONE){
		my = GetMyStatus(work->MyStatus, 0);
		MyStatus_Copy(SaveData_GetMyStatus(work->LinkData.Header->SaveData), my);
	}else{
		for(i=0;i<work->PlayerNum;i++){
			my = GetMyStatus(work->MyStatus, i);
			MyStatus_Copy(CommInfoGetMyStatus(i), my);
		}
	}
}

//--------------------------------------------------------------------------------------------
/**
 * マイステータス取得
 *
 * @param	mystatus_array			マイステータス配列
 * @param	inIdx					インデックス
 *
 * @return	MYSTATUS *				マイステータス
 */
//--------------------------------------------------------------------------------------------
static MYSTATUS *GetMyStatus(MYSTATUS *mystatus_array, const int inIdx)
{
	MYSTATUS *my;
	int ofs;
	u8 *data;

	ofs = inIdx * MyStatus_GetWorkSize();
	data = (u8*)mystatus_array;
	my = (MYSTATUS *)(data + ofs);
	return my;
}

//------------------------------------------------------
//アクセス関数
//------------------------------------------------------

//--------------------------------------------------------------------------------------------
/**
 * ポケスロン参加プレーヤー人数を返す
 *
 * @param	work			ポケスロンワーク
 *
 * @return	u8				人数
 */
//--------------------------------------------------------------------------------------------
u8 PTFrame_GetPlayerNum(PKTHLN_PTR work)
{
	return work->PlayerNum;
}

//--------------------------------------------------------------------------------------------
/**
 * ポケスロン参加者データ先頭アドレスの取得
 *
 * @param	work			ポケスロンワーク
 * @param	inID			ネットID
 *
 * @return	POKETHLON_ENTRY_DATA*	参加者エントリデータポインタ
 */
//--------------------------------------------------------------------------------------------
COMMON_PLAYER_DATA *PTFrame_GetCmnPlayerDataPtrByID(PKTHLN_PTR work, const int inID)
{
	COMMON_PLAYER_DATA *data = &work->CommCmnData.PlayerData[inID];
	return &data[0];
}

//--------------------------------------------------------------------------------------------
/**
 * ポケスロン参加者エントリーデータ先頭アドレスの取得
 *
 * @param	work			ポケスロンワーク
 * @param	inID			ネットID
 *
 * @return	POKETHLON_ENTRY_DATA*	参加者エントリデータポインタ
 */
//--------------------------------------------------------------------------------------------
POKETHLON_ENTRY_DATA *PTFrame_GetEntryDataPtrByID(PKTHLN_PTR work, const int inID)
{
	POKETHLON_ENTRY_DATA *data = work->CommCmnData.PlayerData[inID].EntryData;
	return &data[0];
}

//--------------------------------------------------------------------------------------------
/**
 * セーブデータへのアクセス
 *
 * @param	work			ポケスロンワーク
 *
 * @return	SAVEDATA	*	セーブデータポインタ
 */
//--------------------------------------------------------------------------------------------
SAVEDATA *PTFrame_GetSaveData(PKTHLN_PTR work)
{
	return work->LinkData.Header->SaveData;
}

//--------------------------------------------------------------------------------------------
/**
 * セーブデータにデータを格納するための集計データへのアクセス
 *
 * @param	work			ポケスロンワーク
 *
 * @return	PKTHLN_SVSET_DATA *		集計データポインタ
 */
//--------------------------------------------------------------------------------------------
PKTHLN_SVSET_DATA *PTFrame_GetSvSetDataPtr(PKTHLN_PTR work)
{
	return &work->SvSetData;
}

//--------------------------------------------------------------------------------------------
/**
 * セーブデータにデータを格納するための集計データへのアクセス
 *
 * @param	work			ポケスロンワーク
 * @param	inNetID			ネットID
 *
 * @return	PKTHLN_SVSET_DATA *		集計データポインタ
 */
//--------------------------------------------------------------------------------------------
PKTHLN_POKE_RSLT *PTFrame_GetEvtActDataPtr(PKTHLN_PTR work, const u8 inNetID)
{
	return &work->SvSetData.PokeRslt[inNetID][0];
}

//--------------------------------------------------------------------------------------------
/**
 * 子機が自分で結果を集計する競技のアクションデータの取得
 *
 * @param	work			ポケスロンワーク
 *
 * @return	PKTHLN_POKE_RSLT *		集計データポインタ
 */
//--------------------------------------------------------------------------------------------
PKTHLN_POKE_RSLT *PTFrame_GetMyEvtActDataPtr(PKTHLN_PTR work)
{
	return &(work->EvtActionTmpBuf[0][0]);
}

#if 0
//--------------------------------------------------------------------------------------------
/**
 * ポケスロンエントリーデータ先頭アドレスの取得
 *
 * @param	work			ポケスロンワーク
 *
 * @return	POKETHLON_ENTRY_DATA*	エントリデータポインタ
 */
//--------------------------------------------------------------------------------------------
POKETHLON_ENTRY_DATA *PTFrame_GetEntryDataPtr(PKTHLN_PTR work)
{
	return work->LinkData.CmnPlayerData.EntryData;
}
#endif
//--------------------------------------------------------------------------------------------
/**
 * イベントワークのアロケーション
 *
 * @param	work			ポケスロンワーク
 * @param	size			確保するワークサイズ
 *
 * @return	PTH_EVENT_WORK*	イベントワークポインタ
 */
//--------------------------------------------------------------------------------------------
PTH_EVENT_WORK * PTFrame_AllocEventWork(PKTHLN_PTR work, int size)
{
	work->EventWork = sys_AllocMemory(work->HeapID, size);
	return work->EventWork;
}

//--------------------------------------------------------------------------------------------
/**
 * イベントワークのアロケーション
 *
 * @param	work			ポケスロンワーク
 *
 * @return	PTH_EVENT_WORK*	イベントワークポインタ
 */
//--------------------------------------------------------------------------------------------
void PTFrame_FreeEventWork(PKTHLN_PTR work)
{
	sys_FreeMemoryEz(work->EventWork);
	work->EventWork = NULL;
}

//--------------------------------------------------------------------------------------------
/**
 * イベントワーク取得
 *
 * @param	work			ポケスロンワーク
 *
 * @return	PTH_EVENT_WORK*	イベントワークポインタ
 */
//--------------------------------------------------------------------------------------------
PTH_EVENT_WORK *PTFrame_GetEventWorkPtr(PKTHLN_PTR work)
{
	return work->EventWork;
}

//--------------------------------------------------------------------------------------------
/**
 * ヒープＩＤ取得
 *
 * @param	work			ポケスロンワーク
 *
 * @return	int				ヒープＩＤ
 */
//--------------------------------------------------------------------------------------------
int PTFrame_GetHeapID(PKTHLN_PTR work)
{
	return work->HeapID;
}

//--------------------------------------------------------------------------------------------
/**
 * サブシーケンス取得
 *
 * @param	work			ポケスロンワーク
 *
 * @return	u8				シーケンス
 */
//--------------------------------------------------------------------------------------------
u8 PTFrame_GetSubSeq(PKTHLN_PTR work)
{
	return work->SubSeq;
}

//--------------------------------------------------------------------------------------------
/**
 * サブシーケンスセット
 *
 * @param	work			ポケスロンワーク
 * @param	inSeq			シーケンス
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
void PTFrame_SetSubSeq(PKTHLN_PTR work, const u8 inSeq)
{
	work->SubSeq = inSeq;
}

//--------------------------------------------------------------------------------------------
/**
 * サブシーケンスインクリメント
 *
 * @param	work			ポケスロンワーク
 *
 * @return	u8				シーケンス
 */
//--------------------------------------------------------------------------------------------
void PTFrame_IncSubSeq(PKTHLN_PTR work)
{
	work->SubSeq++;
}

//--------------------------------------------------------------------------------------------
/**
 * 描画開始
 *
 * @param	work			ポケスロンワーク
 * @param	inFlg			TRUE:描画　 FALSE:非描画
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
void PTFrame_SetDraw(PKTHLN_PTR work, const BOOL inFlg)
{
	work->DrawFlg = inFlg;
}

//--------------------------------------------------------------------------------------------
/**
 * 種目コードをセット(コースIDもセット)
 *
 * @param	work		ポケスロンワーク
 * @param	inEventList	種目コードリスト
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
void PTFrame_SetEventNo(PKTHLN_PTR work, const u8 *inEventList)
{
	int i;
	for(i=0;i<work->EventMax;i++){
		work->CommCmnData.EventNo[i] = inEventList[i];
	}
	OS_Printf("%d %d %d\n",
			work->CommCmnData.EventNo[0],work->CommCmnData.EventNo[1],work->CommCmnData.EventNo[2]);

	//コースID設定
	work->CommCmnData.CourseID = PTFrame_GetCourseID(work);
	//選択アプリ用にリンクデータにもコースIDをセット
	work->LinkData.CourseID = work->CommCmnData.CourseID;
}

//--------------------------------------------------------------------------------------------
/**
 * 現在種目コードを取得
 *
 * @param	work		ポケスロンワーク
 *
 * @return	PKTHLN_EVT_CODE			種目コード
 */
//--------------------------------------------------------------------------------------------
PKTHLN_EVT_CODE PTFrame_GetEventCode(PKTHLN_PTR work)
{
	return work->CommCmnData.EventNo[work->EventCounter];
}

//--------------------------------------------------------------------------------------------
/**
 * 指定試合目の種目コードを取得
 *
 * @param	work		ポケスロンワーク
 * @param	inIdx		非通信時：0〜2		通信時：0〜3
 *
 * @return	PKTHLN_EVT_CODE			種目コード
 */
//--------------------------------------------------------------------------------------------
PKTHLN_EVT_CODE PTFrame_GetEventCodeByIdx(PKTHLN_PTR work, const u8 inIdx)
{
	if (inIdx >= work->EventMax){
		GF_ASSERT_MSG(0,"試合インデックス不正\n");
		return 0;
	}else{
		return work->CommCmnData.EventNo[inIdx];
	}
}

//-----------------------------------------------------------------------------
/**
 *	現在のコースIDを取得
 *
 *	@param	PKTHLN_PTR work		ポケスロンワ−ク
 *
 *	@retval	u8(CRS_ID)	コースのインデックス
 */
//-----------------------------------------------------------------------------
u8 PTFrame_GetCourseID(PKTHLN_PTR work)
{
	u8 i, ecnt;
	u8 elem_num;
	BOOL b_comm = ( PTFrame_GetGameType( work ) == PKTHLN_GAME_COMM );
	int* p_no = work->CommCmnData.EventNo;

	// イベントを何個検索するか
	elem_num = b_comm ? PKTHLN_EVT_MAX_COMM : PKTHLN_EVT_MAX_ALONE;

	// 競技テーブルからコースIDを算出
	for( i=0; i<CRS_ID_NUM; i++ )
	{
		BOOL b_check = TRUE;
		for( ecnt=0; ecnt < elem_num; ecnt++ )
		{
			if( p_no[ecnt] != crs_evt_tbl[i][ecnt] ){ b_check = FALSE; break; }
		}

		if( b_check ){ return i; }
	}

	// 例外は全てマスターコース
	return CRS_ID_MAS;
}

//--------------------------------------------------------------------------------------------
/**
 * 現在種目めかを返す
 *
 * @param	work		ポケスロンワーク
 *
 * @return	int			種目数
 */
//--------------------------------------------------------------------------------------------
int PTFrame_GetEventCounter(PKTHLN_PTR work)
{
	return work->EventCounter;
}

//--------------------------------------------------------------------------------------------
/**
 * ゲームタイプを返す
 *
 * @param	work				ポケスロンワーク
 *
 * @return	PKTHLN_GAME_TYPE	ゲームタイプ
 */
//--------------------------------------------------------------------------------------------
PKTHLN_GAME_TYPE PTFrame_GetGameType( PKTHLN_PTR work )
{
	return work->LinkData.Header->GameType;
}

//--------------------------------------------------------------------------------------------
/**
 * データ転送済み人数を返す
 *
 * @param	work				ポケスロンワーク
 *
 * @return	u8					転送済み人数
 */
//--------------------------------------------------------------------------------------------
u8 PTFrame_GetDataSendNum( PKTHLN_PTR work )
{
	return work->DataSendNum;
}

//--------------------------------------------------------------------------------------------
/**
 * データ転送済み人数をインクリメント
 *
 * @param	work				ポケスロンワーク
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
void PTFrame_AddDataSendNum( PKTHLN_PTR work )
{
	work->DataSendNum++;
}

//--------------------------------------------------------------------------------------------
/**
 * データ転送済み人数をクリア
 *
 * @param	work				ポケスロンワーク
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
void PTFrame_ClearDataSendNum( PKTHLN_PTR work )
{
	work->DataSendNum = 0;
}

//--------------------------------------------------------------------------------------------
/**
 * 通信パックシステムポインタを返す
 *
 * @param	work		ポケスロンワーク
 *
 * @return	pack_ptr	通信パックシステムポインタ
 */
//--------------------------------------------------------------------------------------------
COMMPACK_PTR PTFrame_GetCommPackPtr(PKTHLN_PTR work)
{
	return work->CommPackPtr;
}

//--------------------------------------------------------------------------------------------
/**
 * 通信IDを取得する
 *
 * @param	work		ポケスロンワーク
 *
 * @return	int			通信ＩＤ
 */
//--------------------------------------------------------------------------------------------
const int PTFrameGetCurrentID(PKTHLN_PTR work)
{
	return PKTHLN_CommPack_CommGetCurrentID(work->CommPackPtr);
}

//--------------------------------------------------------------------------------------------
/**
 * マイステータス取得
 *
 * @param	work		ポケスロンワーク
 * @param	inID		取得通信ID	0〜3
 *
 * @return	MYSTATUS *	マイステータスポインタ
 */
//--------------------------------------------------------------------------------------------
MYSTATUS *PTFrame_GetMyStatus(PKTHLN_PTR work, const int inID)
{
	return GetMyStatus(work->MyStatus, inID);
}

//--------------------------------------------------------------------------------------------
/**
 * ランキングデータ格納アドレス取得
 *
 * @param	work		ポケスロンワーク
 * @param	inID		取得通信ID	0〜3
 *
 * @return	PKTH_RNK_DATA *	ランキングデータポインタ
 */
//--------------------------------------------------------------------------------------------
PKTH_RNK_DATA *PTFrame_GetRankDataPtr(PKTHLN_PTR work, const int inID)
{
	return &work->RankData[inID];
}

#if 0
//--------------------------------------------------------------------------------------------
/**
 * 転送元ランキングデータ格納アドレス取得
 *
 * @param	work		ポケスロンワーク
 *
 * @return	PKTH_RNK_DATA *	ランキングデータポインタ
 */
//--------------------------------------------------------------------------------------------
PKTH_RNK_DATA *PTFrame_GetOrgRankDataPtr(PKTHLN_PTR work)
{
	return &work->RankDataOrgBuf;
}
#endif

//--------------------------------------------------------------------------------------------
/**
 * 競技用通信データ構造体ポインタの取得
 *
 * @param	work						ポケスロンワーク
 *
 * @return	COMM_EVENT_COMMON_DATA *	通信データポインタ
 */
//--------------------------------------------------------------------------------------------
COMM_EVENT_COMMON_DATA *PTFrame_GetEvtComCmnData(PKTHLN_PTR work)
{
	return &work->EvtComCmnData;
}

//--------------------------------------------------------------------------------------------
/**
 * 競技用通信データ構造体のクリア
 *
 * @param	work						ポケスロンワーク
 *
 */
//--------------------------------------------------------------------------------------------
void PTFrame_ClearEvtComCmnData(PKTHLN_PTR work)
{
	MI_CpuClear8( &work->EvtComCmnData, sizeof(COMM_EVENT_COMMON_DATA));
}

//--------------------------------------------------------------------------------------------
/**
 * 競技アプリ共有用データポインタのセット
 *
 * @param	work		ポケスロンワーク
 * @param	send		競技が用意したデータアドレス
 * @param	recive		格納バッファ
 * @param	inSize		データサイズ
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
void PTFrame_SetEvtShareDataPtr(PKTHLN_PTR work, void * send, void *recive, const int inSize )
{
	work->EvtComCmnData.EvShareData.SendDataPtr = send;
	work->EvtComCmnData.EvShareData.DataPtr = recive;
	work->EvtComCmnData.EvShareData.Size = inSize;
	work->EvtComCmnData.EvShareData.Valid = TRUE;
	OS_Printf("格納アドレスは%x:%x\n",work->EvtComCmnData.EvShareData.DataPtr,recive);
}

//--------------------------------------------------------------------------------------------
/**
 * 競技アプリ共有用データポインタのクリーン（解放ではない）
 *
 * @param	work		ポケスロンワーク
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
void PTFrame_ClearEvtShareDataPtr(PKTHLN_PTR work)
{
	work->EvtComCmnData.EvShareData.SendDataPtr = NULL;
	work->EvtComCmnData.EvShareData.DataPtr = NULL;
	work->EvtComCmnData.EvShareData.Size = 0;
	work->EvtComCmnData.EvShareData.Valid = FALSE;
}

//--------------------------------------------------------------------------------------------
/**
 * 競技アプリ共有用データポインタの取得
 *
 * @param	work		ポケスロンワーク
 *
 * @return	void *		データポインタ
 */
//--------------------------------------------------------------------------------------------
void *PTFrame_GetEvtShareDataPtr(PKTHLN_PTR work)
{
	return work->EvtComCmnData.EvShareData.DataPtr;
}

//--------------------------------------------------------------------------------------------
/**
 * 競技アプリ共有用データポインタの取得
 *
 * @param	work		ポケスロンワーク
 *
 * @return	void *		データポインタ
 */
//--------------------------------------------------------------------------------------------
int PTFrame_GetEvtShareDataSize(PKTHLN_PTR work)
{
	return work->EvtComCmnData.EvShareData.Size;
}

//--------------------------------------------------------------------------------------------
/**
 * 競技結果データサイズ取得
 *
 * @param	work	ポケスロンワーク
 *
 * @return	int		サイズ
 */
//--------------------------------------------------------------------------------------------
int PTFrame_GetEvtResultDataSize(PKTHLN_PTR work)
{
	return sizeof(EVENT_RESULT_DATA);
}

//--------------------------------------------------------------------------------------------
/**
 * 競技結果データセット
 *
 * @param	work		ポケスロンワーク
 * @param	inNetID		ネットID
 * @param	inResult	結果
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
void PTFrame_SetEvtResultOrg(PKTHLN_PTR work, const u8 inNetID, const u16 inResult)
{
	work->RsltDataOrg[inNetID].Data = inResult;
}

//--------------------------------------------------------------------------------------------
/**
 * 競技結果データ取得
 *
 * @param	work		ポケスロンワーク
 * @param	inNetID		ネットＩＤ
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
int PTFrame_GetEvtResultOrg(PKTHLN_PTR work, const u8 inNetID)
{
	return work->RsltDataOrg[inNetID].Data;
}

//--------------------------------------------------------------------------------------------
/**
 * 競技結果データ取得
 *
 * @param	work		ポケスロンワーク
 * @param	inNetID		ネットID
 *
 * @return	int 		結果
 */
//--------------------------------------------------------------------------------------------
int PTFrame_GetEvtResult(PKTHLN_PTR work, const u8 inNetID)
{
	return work->RsltDataAll.All[inNetID].Data;
}

//--------------------------------------------------------------------------------------------
/**
 * 次シーケンス関数インデックスセット
 *
 * @param	work		ポケスロンワーク
 * @param	inIndex		インデックス
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
void PTFrame_SetNextFuncTblIdx(PKTHLN_PTR work, const int inIndex)
{
	if (work->SeqCnt.ChgReqFlg == 1 ){
		GF_ASSERT_MSG(0, "NOW_TBL_IDX = %d  REQ_TBL_IDX = %d\n",
				work->SeqCnt.ActiveSeqData->TblIdxReq, inIndex);
	}
	work->SeqCnt.ChgReqFlg = 1;
	work->SeqCnt.ActiveSeqData->TblIdxReq = inIndex;
	OS_Printf("seqset %d\n",inIndex);
}

//--------------------------------------------------------------------------------------------
/**
 * 次シーケンス関数インデックスセット
 * 既に条件シーケンスインデックスであれば、シーケンスをシフトしないようにする
 *
 * @param	work		ポケスロンワーク
 * @param	inIndex		インデックス
 * @param	inCndIndex	条件インデックス
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
void PTFrame_SetNextFuncTblIdxByCnd(PKTHLN_PTR work, const int inIndex, const int inCndIndex)
{
	if ( work->SeqCnt.ActiveSeqData->TblIdxReq != inCndIndex ){
		if (work->SeqCnt.ChgReqFlg == 1 ){
			GF_ASSERT_MSG(0, "NOW_TBL_IDX = %d  REQ_TBL_IDX = %d\n",
					work->SeqCnt.ActiveSeqData->TblIdxReq, inIndex);
		}
		work->SeqCnt.ChgReqFlg = 1;
		work->SeqCnt.ActiveSeqData->TblIdxReq = inIndex;
		OS_Printf("seqset %d\n",inIndex);
	}else{
		OS_Printf("シーケンスシフトを行いません。\n");
	}
}

//--------------------------------------------------------------------------------------------
/**
 * 通信同期待ちセット
 *
 * @param	work		ポケスロンワーク
 * @param	inID		同期待ちＩＤ
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
void PTFrame_SetSynchroID(PKTHLN_PTR work, const int inID)
{
	//通信時のみＩＤセットを行う
	if (work->LinkData.Header->GameType == PKTHLN_GAME_COMM){
		work->SeqCnt.SynchroID = inID;
	}
}

//--------------------------------------------------------------------------------------------
/**
 * ポケスロンでのデフォルトVブランク関数をセット
 *
 * @param	bgl		Vブランクで使用するBGLポインタ
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
void PTFrame_SetDefaultVBlankFunc(GF_BGL_INI * bgl)
{
	sys_VBlankFuncChange(VBlankFunc, bgl );	// VBlankセット
}

//--------------------------------------------------------------------------------------------------
//競技結果関連
//--------------------------------------------------------------------------------------------
/**
 * 競技結果データ構造体のポインタを返す
 *
 * @param	work		ポケスロンワーク
 *
 * @return	RSLT_PTR
 */
//--------------------------------------------------------------------------------------------
RSLT_PTR PTFrame_GetResultPtr(PKTHLN_PTR work)
{
	return work->Result;
}

//--------------------------------------------------------------------------------------------------
//ポケスロン参加ポケパラメータ関連
//--------------------------------------------------------------------------------------------
/**
 * 参加ポケのパラメータセット
 *
 * @param	work		ポケスロンワーク
 *
 * @return	RSLT_PTR
 */
//--------------------------------------------------------------------------------------------
void PTFrame_SetPkthlnParam(PKTHLN_PTR work)
{
	int i,j;
	ARCHANDLE* handle;
	//アーカイブハンドルを開く
	handle = ArchiveDataHandleOpen( ARC_PKTHPOKE_PARAM, work->HeapID );

	for(i=0;i<ENTRY_MEMBER_NUM_MAX;i++){
		for (j=0;j<ENTRY_MAX;j++){
			int monsno,form,idx;
			monsno = work->CommCmnData.PlayerData[i].EntryData[j].MonsNo;
			form = work->CommCmnData.PlayerData[i].EntryData[j].Form;
			//アーカイブインデックス取得
			idx = PTFrame_GetPokeParamArcIdx(monsno, form);
			//データを格納
			ArchiveDataLoadByHandle( handle, idx, &(work->PokeParam[i][j]) );
		}
	}

	//ハンドルクローズ
	ArchiveDataHandleClose( handle );

#ifdef PM_DEBUG
	for(i=0;i<1/*ENTRY_MEMBER_NUM_MAX*/;i++){
		for (j=0;j<ENTRY_MAX;j++){
			OS_Printf("prm:%d,%d,%d,%d,%d\n",
					work->PokeParam[i][j].Power,
					work->PokeParam[i][j].Speed,
					work->PokeParam[i][j].Jump,
					work->PokeParam[i][j].Stamina,
					work->PokeParam[i][j].Technique);
		}
	}
#endif
}

//--------------------------------------------------------------------------------------------
/**
 * 参加ポケのパラメータ取得
 *
 * @param	work		ポケスロンワーク
 * @param	inNetID		ネットID
 * @param	inEntryNo	エントリーナンバー
 *
 * @return	RSLT_PTR
 */
//--------------------------------------------------------------------------------------------
const PKTHPOKE_PARAM * PTFrame_GetPkthlnParam(PKTHLN_PTR work, const int inNetID, const int inEntryNo)
{
	return &(work->PokeParam[inNetID][inEntryNo]);
}

//--------------------------------------------------------------------------------------------
/**
 * 参加ポケのスペック取得
 *
 * @param	work		ポケスロンワーク
 * @param	inNetID		ネットID
 * @param	inEntryNo	エントリーナンバー
 *
 * @return	RSLT_PTR
 */
//--------------------------------------------------------------------------------------------
extern const POKE_SPEC *PTFrame_GetPokeSpec(PKTHLN_PTR work, const int inNetID, const int inEntryNo)
{
	GF_ASSERT( inNetID < ENTRY_MEMBER_NUM_MAX );
	GF_ASSERT( inEntryNo < ENTRY_MAX );
	return &(work->CommCmnData.PlayerData[inNetID].EntryData[inEntryNo].Spec);
}

//--------------------------------------------------------------------------------------------
/**
 * パラメータをみて、ポケモンタッチ有効半径を返す
 *
 * @param	none
 *
 * @return	タッチ有効半径
 */
//--------------------------------------------------------------------------------------------
const int PTFrame_GetPokeTouchRange(void)
{
	//仕様変更大きさに関係なく固定
	return POKE_RANGE;
}

//--------------------------------------------------------------------------------------------
/**
 * パラメータをみて、ポケモンタッチ有効半径を返す
 *
 * @param	*inParam		ポケスロンポケモンパラメータ
 *
 * @return	タッチ有効半径
 */
//--------------------------------------------------------------------------------------------
const SHADOW_POS PTFrame_GetPokeShdwPosType(const PKTHPOKE_PARAM *inParam)
{
	SHADOW_POS rc;
	if (inParam == NULL){
		return SHADOW_POS_NONE;
	}else{
		switch(inParam->Shadow){
		case SHADOW_TYPE_A:
			rc = SHADOW_POS_A;
			break;
		case SHADOW_TYPE_B:
			rc = SHADOW_POS_B;
			break;
		case SHADOW_TYPE_C:
			rc = SHADOW_POS_C;
			break;
		default:
			GF_ASSERT(0);
			return SHADOW_POS_NONE;
		}
	}
	return rc;
}

//--------------------------------------------------------------------------------------------
/**
 * パラメータをみて、あたり判定データタイプを取得
 *
 * @param	*inParam		ポケスロンポケモンパラメータ
 *
 * @return	タッチ有効半径
 */
//--------------------------------------------------------------------------------------------
const HIT_TYPE PTFrame_GetPokeHitType(const PKTHPOKE_PARAM *inParam)
{
	HIT_TYPE rc;
	if (inParam == NULL){
		return HIT_TYPE_NONE;
	}else{
		switch(inParam->Hit){
		case HIT_TYPE_A:
			rc = HIT_TYPE_A;
			break;
		case HIT_TYPE_B:
			rc = HIT_TYPE_B;
			break;
		case HIT_TYPE_C:
			rc = HIT_TYPE_C;
			break;
		default:
			GF_ASSERT(0);
			return HIT_TYPE_NONE;
		}
	}
	return rc;
}

//--------------------------------------------------------------------------------------------
/**
 * ポケモン情報作成
 *
 * @param	work		ポケスロンワーク
 * @param	inNetID		ネットID
 * @param	inEntryNo	エントリーナンバー
 * @param	outInfo		モンスター情報格納バッファポインタ
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
void PTFrame_SetMonsInfo(PKTHLN_PTR work, const int inNetID, const int inEntryNo, MONS_INFO *outInfo)
{
	POKETHLON_ENTRY_DATA *entry;
	GF_ASSERT(inEntryNo < ENTRY_MAX);
	entry = PTFrame_GetEntryDataPtrByID(work, inNetID);
	outInfo->Rare = entry[inEntryNo].Rare;
	outInfo->MonsNo = entry[inEntryNo].MonsNo;
	outInfo->Form = entry[inEntryNo].Form;
	outInfo->Sex = entry[inEntryNo].Sex;
	outInfo->NetID = inNetID;
	outInfo->PsnlRnd = entry[inEntryNo].PsnlRnd;

	GF_ASSERT( outInfo->MonsNo != 0 );

	//アサート防止
	if (outInfo->MonsNo == 0){
		outInfo->MonsNo = 1;
	}

	{
		PAIR_POKE_INFO info;
		int info_idx = PairPokeIdx_GetIdx( outInfo->MonsNo );
		OS_Printf("連れポケ情報アーカイブインデックス%d\n",info_idx);
		ArchiveDataLoad(&info, ARC_PAIR_POKE_INFO, info_idx);
		if (info.BigSize){
			outInfo->CellType = 1;
		}else{
			outInfo->CellType = 0;
		}
	}
}

//--------------------------------------------------------------------------------------------
/**
 * 競技共通カウントダウンセット	セルセット指定型
 *
 * @param	work		ポケスロンワーク
 * @param	inYOfs		Yオフセット
 * @param	cmm_res_ptr	共通リソースポインタ
 * @param	cl_set_ptr 	アクターセットポインタ
 *
 * @return	CLACT_WORK_PTR *	カウントダウンアクターアドレス
 */
//--------------------------------------------------------------------------------------------
CLACT_WORK_PTR *PTFrame_SetCountDownByClSet( PKTHLN_PTR work,
		                              		 const s16 inYOfs,
									  		 CMN_RES_CNT_PTR cmm_res_ptr,
									  		 CLACT_SET_PTR  cl_set_ptr)
{
	VecFx32 vec;

	work->CDActPtr = CmnRes_CreateCounterAct(cmm_res_ptr, cl_set_ptr,
										0, NNS_G2D_VRAM_TYPE_2DMAIN, work->HeapID );
	work->NRActPtr = CmnRes_CreateNewRecAct(cmm_res_ptr, cl_set_ptr,
										0, work->HeapID );
	work->LastCntPtr = CmnRes_CreateF2X4Act(cmm_res_ptr, cl_set_ptr,
										0, work->HeapID );

	vec.z = 0;
	vec.x = 128*FX32_ONE;
	vec.y = (inYOfs + 96)*FX32_ONE;
	CLACT_SetMatrix( work->CDActPtr, &vec );
	work->CountYOfs = inYOfs;
	{
		VecFx32 cnt_vec;
		cnt_vec.z = 0;
		cnt_vec.x = 128*FX32_ONE;
		cnt_vec.y = (work->CountYOfs + 72)*FX32_ONE;
		CLACT_SetMatrix( work->LastCntPtr, &cnt_vec );
	}
	work->CountSeq = 0;

	vec.y = (inYOfs + 130)*FX32_ONE;
	CLACT_SetMatrix( work->NRActPtr, &vec );

	return &work->CDActPtr;
}

//--------------------------------------------------------------------------------------------
/**
 * 競技共通カウントダウンセット
 *
 * @param	work		ポケスロンワーク
 * @param	inYOfs		Yオフセット
 * @param	cmm_res_ptr	共通リソースポインタ
 * @param	act_cnt_ptr アクター管理ポインタ
 *
 * @return	CLACT_WORK_PTR *	カウントダウンアクターアドレス
 */
//--------------------------------------------------------------------------------------------
CLACT_WORK_PTR *PTFrame_SetCountDown( PKTHLN_PTR work,
		                              const s16 inYOfs,
									  CMN_RES_CNT_PTR cmm_res_ptr,
									  PKTHLN_CLACT_CNT_PTR act_cnt_ptr )
{
	return PTFrame_SetCountDownByClSet( work, inYOfs, cmm_res_ptr,
									  	PkthlnClAct_GetClActSetAdr(act_cnt_ptr) );
}

//--------------------------------------------------------------------------------------------
/**
 * 競技共通ペンアクターセット
 *
 * @param	work		ポケスロンワーク
 * @param	inYOfs		上下画面マージンオフセット
 * @param	cmm_res_ptr	共通リソースポインタ
 * @param	cl_set_ptr アクター管理ポインタ
 * @param	inVramType	VRAMタイプ
 * @param	inNum		セット数
 * @param	inPosAry	セット座標配列
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
void PTFrame_SetPenByClSet( PKTHLN_PTR work,
		                   const s16 inYOfs,
						   CMN_RES_CNT_PTR cmm_res_ptr,
						   CLACT_SET_PTR  cl_set_ptr,
						   const int inVramType,
						   const u8 inNum,
						   const PEN_POS *inPosAry)
{


	u8 i;
	work->PenNum = inNum;
	for(i=0;i<inNum;i++){
		VecFx32 vec;
		work->PenActPtr[i] = CmnRes_CreatePenAct(cmm_res_ptr, cl_set_ptr, inVramType,
										0, work->HeapID );
		//座標セット
		vec.z = 0;
		vec.x = inPosAry[i].X*FX32_ONE;
		vec.y = (inYOfs + inPosAry[i].Y)*FX32_ONE;
		CLACT_SetMatrix( work->PenActPtr[i], &vec );
	}

	for(;i<ENTRY_MAX;i++){
		work->PenActPtr[i] = NULL;
	}
	//シーケンス初期化
	work->PenSeq = 0;
}

//--------------------------------------------------------------------------------------------
/**
 * 競技共通ペンアクターセット
 *
 * @param	work		ポケスロンワーク
 * @param	inYOfs		上下画面マージンオフセット
 * @param	cmm_res_ptr	共通リソースポインタ
 * @param	act_cnt_ptr アクター管理ポインタ
 * @param	inVramType	VRAMタイプ
 * @param	inNum		セット数
 * @param	inPosAry	セット座標配列
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
void PTFrame_SetPen( PKTHLN_PTR work,
		                   const s16 inYOfs,
						   CMN_RES_CNT_PTR cmm_res_ptr,
						   PKTHLN_CLACT_CNT_PTR act_cnt_ptr,
						   const int inVramType,
						   const u8 inNum,
						   const PEN_POS *inPosAry)
{
	PTFrame_SetPenByClSet( work, inYOfs, cmm_res_ptr, PkthlnClAct_GetClActSetAdr(act_cnt_ptr),
						   inVramType, inNum, inPosAry);
}

//--------------------------------------------------------------------------------------------
/**
 * 競技共通カウントダウン
 *
 * @param	work		ポケスロンワーク
 *
 * @return	BOOL		カウントダウン終了でTRUEを返す
 */
//--------------------------------------------------------------------------------------------
BOOL PTFrame_CountDown(PKTHLN_PTR work)
{
	BOOL rc;

	rc = FALSE;
	//ペンアニメ
	switch(work->PenSeq){
	case 0:
		//ペンアニメスタート
		Snd_SePlay(SE_THLON_PEN_TOUCH);
		StartPenAnm(work);
		work->PenSeq++;
		break;
	case 1:
		//ペンアニメ終了待ち
		if ( CheckPenAnmEnd(work) ){
			work->PenSeq++;
			Snd_PlayerPause( PLAYER_BGM, FALSE );
		}
		break;
	case 2:
		//カウントダウン

///		OS_Printf("カウント:%d\n",work->StartCount);
		if (work->StartCount == COUNTDOWN_MARGINE*0){
			Snd_SePlay( SE_THLON_GAME_COUNT );
			CLACT_SetDrawFlag(work->CDActPtr, 1);
			CLACT_AnmChg( work->CDActPtr, 0 );
		}else if(work->StartCount == COUNTDOWN_MARGINE*1){
			Snd_SePlay( SE_THLON_GAME_COUNT );
			CLACT_AnmChg( work->CDActPtr, 1 );
		}else if(work->StartCount == COUNTDOWN_MARGINE*2){
			Snd_SePlay( SE_THLON_GAME_COUNT );
			CLACT_AnmChg( work->CDActPtr, 2 );
		}

		work->StartCount++;

		if (work->StartCount > START_COUNT_MAX){
			Snd_SePlay( SE_THLON_GAME_START );		//開始SE
			//カウントダウン消す
			CLACT_SetDrawFlag(work->CDActPtr, 0);
			work->StartCount = 0;
			rc = TRUE;
		}
	}
	return rc;
}

//--------------------------------------------------------------------------------------------
/**
 * ラスト３秒前表示
 *
 * @param	work		ポケスロンワーク
 * @param	inTime		現在タイム
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
void PTFrame_DispLastCount(PKTHLN_PTR work, const int inTime)
{
	int sec;
	sec = (inTime+29)/30;
	if (sec <= 0){
		//非表示
		CLACT_SetDrawFlag(work->LastCntPtr, 0);
	}else if(sec <= 3){
		if (work->SeTmpSec!=sec){		//初検出で鳴らす
			Snd_SePlay( SE_THLON_LAST_THREE );
			work->SeTmpSec = sec;
		}
		CLACT_SetDrawFlag(work->LastCntPtr, 1);
		CLACT_AnmChg( work->LastCntPtr, sec+1 );

	}else{
		CLACT_SetDrawFlag(work->LastCntPtr, 0);
	}
}


//--------------------------------------------------------------------------------------------
/**
 * 競技共通▼マーカー初期化
 *
 * @param	work		ポケスロンワーク
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
void PTFrame_InitPosMarker(PKTHLN_PTR work)
{
	u8 i;
	work->PosMarkerMng.NowEntry = 0;
	for (i=0;i<ENTRY_MAX;i++){
		GF_ASSERT_MSG( (!work->PosMarkerMng.Marker[i].Valid),"使用中です\n");
		work->PosMarkerMng.Marker[i].PokePtr = NULL;
		work->PosMarkerMng.Marker[i].ActPtr = NULL;
		work->PosMarkerMng.Marker[i].TcbPtr = NULL;
	}
}

//--------------------------------------------------------------------------------------------
/**
 * 競技共通▼マーカーセット
 *
 * @param	work		ポケスロンワーク
 * @param	pPokePtr	ポケモンアクター
 * @param	pClActSetPtr	セルアクターセット
 * @param	inBGPriority	BGプライオリティ
 *
 * @return	CLACT_WORK_PTR   アクターワークポインタ
 */
//--------------------------------------------------------------------------------------------
CLACT_WORK_PTR PTFrame_SetPosMarker( PKTHLN_PTR work, POKE_ACT_PTR pPokePtr,
									 CMN_RES_CNT_PTR pResCntPtr,
						   			 CLACT_SET_PTR  pClActSetPtr,
									 const int inBGPriority)
{
	u8 idx;
	POS_MARKER *marker;

	if (work->PosMarkerMng.NowEntry >= ENTRY_MAX){
		GF_ASSERT_MSG(0, "登録数オーバー\n");
		return NULL;
	}
	idx = work->PosMarkerMng.NowEntry;
	marker = &(work->PosMarkerMng.Marker[idx]);

	marker->Valid = TRUE;
	marker->PokePtr = pPokePtr;
	marker->ActPtr = CmnRes_CreateCurAct( pResCntPtr, pClActSetPtr, inBGPriority, work->HeapID );

	marker->TcbPtr = TCB_Add(PosMarkerTask, marker, POS_MARKER_TCB_PRI);

	work->PosMarkerMng.NowEntry++;

	return marker->ActPtr;
}

//--------------------------------------------------------------------------------------------
/**
 * 競技共通▼マーカー終了
 *
 * @param	work		ポケスロンワーク
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
void PTFrame_EndPosMarker(PKTHLN_PTR work)
{
	u8 i;
	for (i=0;i<ENTRY_MAX;i++){
		work->PosMarkerMng.Marker[i].Valid = FALSE;
		work->PosMarkerMng.Marker[i].PokePtr = NULL;
		work->PosMarkerMng.Marker[i].ActPtr = NULL;
		TCB_Delete(work->PosMarkerMng.Marker[i].TcbPtr);
		work->PosMarkerMng.Marker[i].TcbPtr = NULL;
	}
}

//--------------------------------------------------------------------------------------------
/**
 * 競技共通▼マーカー変更
 *
 * @param	work		ポケスロンワーク
 * @param	inIdx		変更するマーカーインデックス（0〜2）
 * @param	inAnmNo		アニメナンバー（0 or 1）
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
void PTFrame_ChgPosMarker( PKTHLN_PTR work, const u8 inIdx, const u8 inAnmNo )
{
	CLACT_AnmChgCheck( work->PosMarkerMng.Marker[inIdx].ActPtr, inAnmNo );
}

//--------------------------------------------------------------------------------------------
/**
 * 競技共通▼マーカーアニメストップ
 *
 * @param	work		ポケスロンワーク
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
void PTFrame_StopPosMarker(PKTHLN_PTR work)
{
	u8 i;
	for (i=0;i<ENTRY_MAX;i++){
		GF_ASSERT(work->PosMarkerMng.Marker[i].Valid);
		CLACT_SetAnmFlag( work->PosMarkerMng.Marker[i].ActPtr, 0);
	}
}

//--------------------------------------------------------------------------------------------
/**
 * 競技共通ペンアクターアニメスタート
 *
 * @param	work		ポケスロンワーク
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void StartPenAnm(PKTHLN_PTR work)
{
	u8 i;
	if (!work->PenNum){
		return;
	}

	for(i=0;i<work->PenNum;i++){
		CLACT_SetDrawFlag(work->PenActPtr[i], 1);
		CLACT_AnmChg( work->PenActPtr[i], 0 );
	}
}

//--------------------------------------------------------------------------------------------
/**
 * 競技共通ペンアクターアニメ終了監視
 *
 * @param	work		ポケスロンワーク
 *
 * @return	BOOL		TRUE:終了		FALSE:継続
 */
//--------------------------------------------------------------------------------------------
static BOOL CheckPenAnmEnd(PKTHLN_PTR work)
{
	if (!work->PenNum){
		return TRUE;
	}

	//アニメ終了は配列のはじめのセルアクターで監視することにする
	if ( !CLACT_AnmActiveCheck( work->PenActPtr[0] ) ){
		u8 i;
		//ペンバニッシュ
		for(i=0;i<work->PenNum;i++){
			CLACT_SetDrawFlag(work->PenActPtr[i], 0);
		}
		return TRUE;
	}
	return FALSE;
}

//--------------------------------------------------------------------------------------------
/**
 * レコード表示ＢＧの設定
 *
 * @param	work		ポケスロンワーク
 * @param	inRecBGMask		レコード表示ＢＧマスク
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
void PTFrame_SetRecBGMask(PKTHLN_PTR work, const int inRecBGMask)
{
	work->RecBGMask = inRecBGMask;
}

//--------------------------------------------------------------------------------------------
/**
 * 競技共通終了表示
 *
 * @param	work		ポケスロンワーク
 *
 * @return	BOOL		ＥＮＤ表示終了でTRUEを返す
 */
//--------------------------------------------------------------------------------------------
BOOL PTFrame_DispEnd(PKTHLN_PTR work)
{
	VecFx32 vec;

	switch(work->CountSeq){
	case 0:
		//３秒前カウント非表示
		CLACT_SetDrawFlag(work->LastCntPtr, 0);

		Snd_SePlay( SE_THLON_GAME_END );		//終了SE
		//座標セット
		vec.z = 0;
		vec.x = 128*FX32_ONE;
		vec.y = (work->CountYOfs + 72)*FX32_ONE;
		CLACT_SetMatrix( work->CDActPtr, &vec );
		//エンド表示
		CLACT_AnmChg( work->CDActPtr, 3 );
		CLACT_SetDrawFlag(work->CDActPtr, 1);
		work->CountSeq = 1;
		break;
	case 1:
		work->StartCount++;
		if (work->StartCount > REC_WAIT){
			work->StartCount = 0;
			work->CountSeq = 2;
		}
		break;
	case 2:
		//コールバック関数が登録されている場合はここでコールする
		if (work->RecordCallBack != NULL){
			//レコードコールバック
			work->RecordCallBack(work);
		}

		//ニューレコード判定
		if ( CheckNewRecord(work) ){
			Snd_SePlay( SE_THLON_NEWRECORD );
			CLACT_AnmChg( work->NRActPtr, 0 );
			CLACT_SetDrawFlag(work->NRActPtr, 1);
		}
		//レコード表示
		GF_Disp_GX_VisibleControl( work->RecBGMask, VISIBLE_ON );
		//コールバック関数ポインタにNULLセット
		work->RecordCallBack = NULL;
		work->CountSeq = 3;
		break;
	case 3:
		//レコード表示ウェイト
		work->StartCount++;
		if (work->StartCount > COUNT_MAX){
			work->StartCount = 0;
			work->CountSeq = 4;
			return TRUE;
		}
		break;
	case 4:
		return TRUE;
	}
	return FALSE;
}

//--------------------------------------------------------------------------------------------
/**
 * カウントダウンアクターのアドレスを返す
 *
 * @param	work		ポケスロンワーク
 *
 * @return	CLACT_WORK_PTR
 */
//--------------------------------------------------------------------------------------------
CLACT_WORK_PTR *PTFrame_GetCountDownActAdr(PKTHLN_PTR work)
{
	return &work->CDActPtr;
}

//--------------------------------------------------------------------------------------------
/**
 * ポケパラメータアーカイブインデックス取得
 *
 * @param	inMonsNo		モンスターナンバー
 * @param	inForm			フォルム
 *
 * @return  int 			アーカイブインデックス
 */
//--------------------------------------------------------------------------------------------
const int PTFrame_GetPokeParamArcIdx(const int inMonsNo, const int inForm)
{
	return PkthlnPokeArcNo[ inMonsNo ] + inForm;
}


//====================================================================================================
//描画関数
//====================================================================================================

//----------------------------------------------------------------------------
/**
 *	@brief	競技描画関数
 *
 *	@param	work		ワーク
 *
 *	@return　none
 */
//-----------------------------------------------------------------------------
static void	EventDraw(PKTHLN_PTR work)
{
	if (work->DrawFlg){
		//描画
		work->FuncTbl->DrawFunc(work, NULL);
	}
}

//====================================================================================================
//フレームワークシーケンス関数群
//====================================================================================================

//----------------------------------------------------------------------------
/**
 *	@brief	アプリ開始前種目ナンバー共有
 *
 *	@param	work		ワーク
 *	@param	*seq		シーケンサ
 *
 *	@return	BOOL		FALSE
 */
//-----------------------------------------------------------------------------
static BOOL FrameFunc_ShareEventNo(PKTHLN_PTR work, u8 *seq)
{
	BOOL rc = TRUE;
	//親なら種目転送、そうでなければ、コールバックウェイト
	if (PTFrameGetCurrentID(work) == COMM_PARENT_ID){
		//コースIDから、今回の競技を決定
		DecideEvt( work->LinkData.Header, work->EventMax, work->EvtOrg  );
		//転送
		rc = PKTHLN_CommPack_CommSendData( COMM_PKTHLN_SET_EVENT_NO,
				work->EvtOrg, CommPkthlnGetEventNoSize(),
			 	work->CommPackPtr );
	}

	if (rc){
		//コールバック待ちシーケンスへ
		PTFrame_SetNextFuncTblIdxByCnd(work, FRAME_SEQ_CALLBACK_WAIT, FRAME_SEQ_POKE_SELECT);
	}else{
		OS_Printf("種目ナンバー送信失敗\n");
	}

	return FALSE;
}

//----------------------------------------------------------------------------
/**
 *	@brief	ポケスロン参加ポケモンの選択
 *
 *	@param	work		ワーク
 *	@param	*seq		シーケンサ
 *
 *	@return	BOOL 		FALSE
 */
//-----------------------------------------------------------------------------
static BOOL FrameFunc_PokemonSelect(PKTHLN_PTR work, u8 *seq)
{
	if ( ProcMain(work->PokeSelectProc) ){
		//通信同期待ち
///		PTFrame_SetSynchroID(work, PKTHLN_SYNC_ID_SELECT_WAIT);		//選択待ちシーケンスができたので不要
		//ポケモン選択プロセスを削除
		PROC_Delete(work->PokeSelectProc);

		if ( work->LinkData.Header->GameType == PKTHLN_GAME_ALONE ){	//非通信
			//非通信時のみキャンセル終了したかをチェック
			if (work->LinkData.SelectCancel){
				OS_Printf("非通信時の選択キャンセルによる終了\n");
				work->LinkData.Header->RetExit = 1;	//Exitフラグセット
				PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_END);			//キャンセル終了
			}else{
				work->LinkData.Header->RetExit = 0;	//Exitフラグセット
				//シーケンスシフト
				PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_POKE_ENTRY);	//一人用ポケスロン開始
			}
		}else{															//通信
			work->LinkData.Header->RetExit = 0;	//Exitフラグセット
			//シーケンスシフト
			PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_WAIT_POKE_SEL);	//通信ポケスロン開始
		}
	}
	return FALSE;
}

//----------------------------------------------------------------------------
/**
 *	@brief	ポケモン選択待ち
 *
 *	@param	work		ワーク
 *	@param	*seq		シーケンサ
 *
 *	@return	BOOL		FALSE
 */
//-----------------------------------------------------------------------------
static FrameFunc_WaitPokeSel(PKTHLN_PTR work, u8 *seq)
{
	switch(*seq){
	case 0:		//セットアップ
#ifdef PM_DEBUG
		//ポケスロン残りヒープセット
		PkthHeap = sys_GetHeapFreeSize(HEAPID_POKETHLON);
		OS_Printf("PKTHLN_HEAP_REST:%d\n",PkthHeap);
#endif
		OS_Printf("ポケモン選択待ちセット\n");
		//ファンクションテーブルのセット
		work->FuncTbl = &PE_CommWaitFuncTbl;
		work->SubSeq = 0;
		//シーケンス関数テーブルのセット
		InitSeqData(&CommWaitFuncTbl[0], &work->EventSeq);
		(*seq)++;
		break;
	case 1:		//初期化
		OS_Printf("選択待ち初期化\n");
		if ( FuncInit(work) ){
			(*seq)++;
		}
		break;
	case 2:		//メイン
		{
			PKTHLN_FUNC func;
			if (work->EventSeq.FuncTbl == NULL){
				(*seq)++;
				break;
			}
			//アクティブシーケンスがフレームシーケンスの場合は、イベントシーケンスに変更する
			if (work->SeqCnt.ActiveSeqData == &work->FrameSeq){
				OS_Printf("アクティブシーケンスをイベントシーケンスにセット\n");
				work->SeqCnt.ActiveSeqData = &work->EventSeq;
				work->SeqCnt.ChgReqFlg = 0;
			}

			//シーケンスの実行
			func = work->EventSeq.FuncTbl[work->EventSeq.TblIdx];
			if ( func(work, &work->EventSeq.SubSeq) ){
				//描画を禁止
				PTFrame_SetDraw(work, FALSE);
				//アクティブシーケンスをフレームシーケンスに戻す
				work->SeqCnt.ActiveSeqData = &work->FrameSeq;
				work->SeqCnt.ChgReqFlg = 0;
				(*seq)++;
				break;
			}
		}
		break;
	case 3:		//終了
		OS_Printf("ポケモン選択待ち終了\n");
		work->FuncTbl->EndFunc(work, NULL);
		//イベントワークの解放忘れをチェック
		GF_ASSERT_MSG(work->EventWork == NULL,"イベントワークの解放忘れ\n");
#ifdef PM_DEBUG
		//ヒープ調べる
		if(PkthHeap != sys_GetHeapFreeSize(HEAPID_POKETHLON)){
			GF_ASSERT_MSG(0, "PKTH_HEAP SIZE %d < %d\n",
							PkthHeap, sys_GetHeapFreeSize(HEAPID_POKETHLON));
		}
#endif
		//シーケンスシフト(エントリシーケンスへ)
		PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_POKE_ENTRY);
	}

	return FALSE;
}

//----------------------------------------------------------------------------
/**
 *	@brief	ポケモンエントリー集計
 *
 *	@param	work		ワーク
 *	@param	*seq		シーケンサ
 *
 *	@return	BOOL	FALSE
 */
//-----------------------------------------------------------------------------
static BOOL FrameFunc_PokemonEntry(PKTHLN_PTR work, u8 *seq)
{
	BOOL rc;
	//ＮＰＣ以外の参加者のパーソンコードは0固定
	work->LinkData.CmnPlayerData.PersonCode = 0;
	//自分のエントリポケモンデータを転送
	rc = PKTHLN_CommPack_CommSendHugeData( COMM_PKTHLN_POKE_ADD_UP,
				&work->LinkData.CmnPlayerData, CommPkthlnGetPokeAddUpSize(),
				work->CommPackPtr );
	if (rc){
		//コールバック待ちシーケンスへ
		PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_CALLBACK_WAIT);
	}else{
		OS_Printf("ポケモンエントリーデータ送信失敗\n");
	}

	return FALSE;
}

//----------------------------------------------------------------------------
/**
 *	@brief	親だけが来るシーケンス　ポケモンデータの共有
 *
 *	@param	work		ワーク
 *	@param	*seq		シーケンサ
 *
 *	@return	BOOL	FALSE
 */
//-----------------------------------------------------------------------------
static BOOL FrameFunc_ParentSharePokemon(PKTHLN_PTR work, u8 *seq)
{
	BOOL rc;
	COMMON_PLAYER_DATA *data;
	OS_Printf("親がデータを送信\n");

	//集まったら全員に4人分集計データを送信(格納バッファを転送元バッファとして使用する)
	data = PTFrame_GetCmnPlayerDataPtrByID(work, 0);

	rc = PKTHLN_CommPack_CommSendHugeData( COMM_PKTHLN_ALL_POKE_DATA,
				data, CommPkthlnGetAllPokeDataSize(),
				PTFrame_GetCommPackPtr(work) );
	if (rc){
		//コールバック待ちシーケンスへ
		PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_CALLBACK_WAIT);
	}else{
		OS_Printf("親：ポケモンデータ送信失敗\n");
	}
	return FALSE;
}


//----------------------------------------------------------------------------
/**
 *	@brief	マイステータスセット
 *
 *	@param	work		ワーク
 *	@param	*seq		シーケンサ
 *
 *	@return	BOOL		FALSE
 */
//-----------------------------------------------------------------------------
static BOOL FrameFunc_SetMyStatus(PKTHLN_PTR work, u8 *seq)
{
	BOOL rc = TRUE;
	//親ならマイステータス転送
	if (PTFrameGetCurrentID(work) == COMM_PARENT_ID){
		//全員分のマイステータスを転送
		rc = PKTHLN_CommPack_CommSendHugeData( COMM_PKTHLN_SET_MY_STATUS,
				work->MyStatus, CommPkthlnGetAllMyStatusSize(),
				work->CommPackPtr );
	}

	if (rc){
		//コールバック待ちシーケンスへ
		PTFrame_SetNextFuncTblIdxByCnd(work, FRAME_SEQ_CALLBACK_WAIT, FRAME_SEQ_GET_RANKDATA);
	}else{
		OS_Printf("マイステータス送信失敗\n");
	}

	return FALSE;
}

//----------------------------------------------------------------------------
/**
 *	@brief	ランキングデータセット
 *
 *	@param	work		ワーク
 *	@param	*seq		シーケンサ
 *
 *	@return	BOOL		FALSE
 */
//-----------------------------------------------------------------------------
static BOOL FrameFunc_SendMyRankData(PKTHLN_PTR work, u8 *seq)
{
	BOOL rc;
	work->RankDataOrg = *PkthlnSv_GetRnkData(PkthlnSv_GetSaveData(work->LinkData.Header->SaveData));
	//自分のランキングデータを親に転送
	rc = PKTHLN_CommPack_CommSendHugeData( COMM_PKTHLN_GET_MY_RANK_DATA,
				&work->RankDataOrg, CommPkthlnGetRankDataSize(),
				work->CommPackPtr );
	if (rc){
		//コールバック待ちシーケンスへ
		PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_CALLBACK_WAIT);
	}else{
		OS_Printf("ランキングデータを送信失敗\n");
	}

	return FALSE;
}
#if 0
//----------------------------------------------------------------------------
/**
 *	@brief	親だけが来るシーケンス　ランキングデータの共有
 *
 *	@param	work		ワーク
 *	@param	*seq		シーケンサ
 *
 *	@return	BOOL		FALSE
 */
//-----------------------------------------------------------------------------
static BOOL FrameFunc_ParentShareRankData(PKTHLN_PTR work, u8 *seq)
{
	BOOL rc;
	void *adr;
	OS_Printf("親が全員にランキングデータを送信\n");
	//集まったら全員に集計データを送信
	adr = PTFrame_GetRankDataPtr(work, 0);
	rc = PKTHLN_CommPack_CommSendHugeData( COMM_PKTHLN_RECIVE_RANK_DATA,
					adr, CommPkthlnGetAllRankDataSize(),
					PTFrame_GetCommPackPtr(work) );
	if (rc){
		//コールバック待ちシーケンスへ
		PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_CALLBACK_WAIT);
	}else{
		OS_Printf("親：ランキングデータ送信失敗\n");
	}

	return FALSE;
}
#endif
//----------------------------------------------------------------------------
/**
 *	@brief	開会式セット
 *
 *	@param	work		ワーク
 *	@param	*seq		シーケンサ
 *
 *	@return	BOOL		FALSE
 */
//-----------------------------------------------------------------------------
static BOOL FrameFuncOpeningSet(PKTHLN_PTR work, u8 *seq)
{
	u8 i;
#ifdef PM_DEBUG
	//ポケスロン残りヒープセット
	PkthHeap = sys_GetHeapFreeSize(HEAPID_POKETHLON);
	OS_Printf("PKTHLN_HEAP_REST:%d\n",PkthHeap);
#endif
	OS_Printf("開会式セット\n");

#if 1
#ifdef PM_DEBUG
	//ランキングデータプリント
	for (i=0;i<4;i++){
		OS_Printf("rank___%d\n",i);
		OS_Printf("%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
				work->RankData[i].PlayMinute,
				work->RankData[i].AlonePlay,		//非通信プレイ回数
				work->RankData[i].AloneWin,		//非通信優勝回数
				work->RankData[i].AloneLose,		//非通信最下位回数
				work->RankData[i].BonusNum,		//ボーナス取得回数
				work->RankData[i].TouchNum,		//タッチ回数
				work->RankData[i].PokeFail,		//ポケモン失敗回数
				work->RankData[i].PokeJump,		//ポケモンジャンプ回数
				work->RankData[i].PointGet,		//得点取得回数
				work->RankData[i].PokeAttack);
		OS_Printf("%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
				work->RankData[i].PokeFall,		//ポケモン落下回数
				work->RankData[i].PokeDash,		//ポケモンダッシュ回数
				work->RankData[i].PokeChange,		//ポケモン交代回数
				work->RankData[i].OwnGoal,		//自殺点回数
				work->RankData[i].CommPlay,		//通信プレイ回数
				work->RankData[i].CommWin,		//通信優勝回数
				work->RankData[i].CommLose,		//通信最下位回数
				work->RankData[i].EvtLoseNum,					//競技最下位回数（競技間で共通）
				work->RankData[i].FunNum	);			//ファンの数
	}
#endif
#endif
	//時間経過開始
	work->OpeningStart = TRUE;

	//通信データクリア
	PTFrame_ClearEvtComCmnData(work);

	//ファンクションテーブルのセット
	work->FuncTbl = &PE_OpeningFuncTbl;
	work->SubSeq = 0;
	//シーケンス関数テーブルのセット
	InitSeqData(&OpeningFuncTbl[0], &work->EventSeq);
	//描画関数のスイッチ
//	work->PokethlonDraw = EventDraw;
	//シーケンスシフト
	PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_OPENING_INIT);
	return FALSE;
}

//----------------------------------------------------------------------------
/**
 *	@brief	開会式初期化
 *
 *	@param	work		ワーク
 *	@param	*seq		シーケンサ
 *
 *	@return	BOOL		FALSE
 */
//-----------------------------------------------------------------------------
static BOOL FrameFuncOpeningInit(PKTHLN_PTR work, u8 *seq)
{
	OS_Printf("開会式初期化\n");
	if ( FuncInit(work) ){
		//通信データサイズを設定
		{
			COMM_EVENT_COMMON_DATA * data;
			data = PTFrame_GetEvtComCmnData(work);
			data->SendData.Share = 0;
			data->SendShareData.Share = 1;

			//38バイト制限有効
			PKTHLN_CommPack_SetSizeBind( PTFrame_GetCommPackPtr(work), 1 );
		}
		//同期を取って次のシーケンスで開会式メイン
		PTFrame_SetSynchroID(work, PKTHLN_SYNC_ID_OPENING_INIT_WAIT);
		//シーケンスシフト
		PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_OPENING_MAIN);
		//サウンドシーン変更
		Snd_SceneSet( SND_SCENE_DUMMY );
		Snd_DataSetByScene( SND_SCENE_THLON_OPED, SEQ_GS_PT_OPEN, 0 );
	}
	return FALSE;
}

//開会式メイン
//----------------------------------------------------------------------------
/**
 *	@brief	開会式メイン
 *
 *	@param	work		ワーク
 *	@param	*seq		シーケンサ
 *
 *	@return	BOOL		FALSE
 */
//-----------------------------------------------------------------------------
static BOOL FrameFuncOpeningMain(PKTHLN_PTR work, u8 *seq)
{
	PKTHLN_FUNC func;
	if (work->EventSeq.FuncTbl == NULL){
		//シーケンスシフト
		PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_OPENING_END);
		return FALSE;
	}

	//アクティブシーケンスがフレームシーケンスの場合は、イベントシーケンスに変更する
	if (work->SeqCnt.ActiveSeqData == &work->FrameSeq){
		OS_Printf("アクティブシーケンスをイベントシーケンスにセット\n");
		work->SeqCnt.ActiveSeqData = &work->EventSeq;
		work->SeqCnt.ChgReqFlg = 0;
	}

	//シーケンスの実行
	func = work->EventSeq.FuncTbl[work->EventSeq.TblIdx];
	if ( func(work, &work->EventSeq.SubSeq) ){
		//描画を禁止
		PTFrame_SetDraw(work, FALSE);
		//アクティブシーケンスをフレームシーケンスに戻す
		work->SeqCnt.ActiveSeqData = &work->FrameSeq;
		work->SeqCnt.ChgReqFlg = 0;
		//シーケンスシフト
		PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_OPENING_END);
	}else{
		// 競技中は常に転送
		if ( PTFrameGetCurrentID(work) == COMM_PARENT_ID ){		//親
			PKTHLN_CommPack_CommSendData( COMM_PKTHLN_EVT_CMN_DATA, &work->EvtComCmnData.SendShareData,
					CommPkthlnGetEvtCmnDataSize(), work->CommPackPtr );
			{
				//親データは直接レシーバにセット
				PTHLN_COMM_DATA *child;
				PTHLN_COMM_DATA *child_rec;
				child_rec = PKTHLN_CommPack_GetData(&work->EvtComCmnData.ReciveData[0]);
				child = PKTHLN_CommPack_GetData(&work->EvtComCmnData.SendData);
				(*child_rec) = (*child);
			}
		}else{		//子
			PKTHLN_CommPack_CommSendData( COMM_PKTHLN_EVT_CMN_DATA, &work->EvtComCmnData.SendData,
					CommPkthlnGetEvtCmnDataSize(), work->CommPackPtr );
		}
	}
	return FALSE;
}

//----------------------------------------------------------------------------
/**
 *	@brief	開会式終了
 *
 *	@param	work		ワーク
 *	@param	*seq		シーケンサ
 *
 *	@return	BOOL		FALSE
 */
//-----------------------------------------------------------------------------
static BOOL FrameFuncOpeningEnd(PKTHLN_PTR work, u8 *seq)
{
	OS_Printf("開会式終了\n");
	work->FuncTbl->EndFunc(work, NULL);
	//イベントワークの解放忘れをチェック
	GF_ASSERT_MSG(work->EventWork == NULL,"イベントワークの解放忘れ\n");
	//フレームワーク描画関数を描画関数としてセット
//	work->PokethlonDraw = FrameDraw;
#ifdef PM_DEBUG
	//ヒープ調べる
	if(PkthHeap != sys_GetHeapFreeSize(HEAPID_POKETHLON)){
		GF_ASSERT_MSG(0, "PKTH_HEAP SIZE %d < %d\n",
						PkthHeap, sys_GetHeapFreeSize(HEAPID_POKETHLON));
	}
#endif

#ifdef PM_DEBUG
		OS_Printf("競技前のアクションポイント\n");
		PrintActPoint(work);
#endif
	//シーケンスシフト
	PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_EVT_CALL_SET);

	return FALSE;
}

//----------------------------------------------------------------------------
/**
 *	@brief	競技タイトルコールセット
 *
 *	@param	work		ワーク
 *	@param	*seq		シーケンサ
 *
 *	@return	BOOL		FALSE
 */
//-----------------------------------------------------------------------------
static BOOL FrameFuncEvtCallSet(PKTHLN_PTR work, u8 *seq)
{
	OS_Printf("タイトルコールセット\n");

	//ファンクションテーブルのセット
	work->FuncTbl = &PE_EvtStartFuncTbl;
	work->SubSeq = 0;
	//シーケンス関数テーブルのセット
	InitSeqData(&EvtStartFuncTbl[0], &work->EventSeq);
	//描画関数のスイッチ
//	work->PokethlonDraw = EventDraw;
	//シーケンスシフト
	PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_EVT_CALL_INIT);

	return FALSE;
}

//----------------------------------------------------------------------------
/**
 *	@brief	競技タイトルコール初期化
 *
 *	@param	work		ワーク
 *	@param	*seq		シーケンサ
 *
 *	@return	BOOL		FALSE
 */
//-----------------------------------------------------------------------------
static BOOL FrameFuncEvtCallInit(PKTHLN_PTR work, u8 *seq)
{
	OS_Printf("タイトルコール初期化\n");
	if ( FuncInit(work) ){
		//同期を取って次のシーケンスで開会式メイン
		PTFrame_SetSynchroID(work, PKTHLN_SYNC_ID_EVT_CALL_INIT_WAIT);
		//シーケンスシフト
		PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_EVT_CALL_MAIN);
	}
	return FALSE;
}

//----------------------------------------------------------------------------
/**
 *	@brief	競技タイトルコールメイン
 *
 *	@param	work		ワーク
 *	@param	*seq		シーケンサ
 *
 *	@return	BOOL		FALSE
 */
//-----------------------------------------------------------------------------
static BOOL FrameFuncEvtCallMain(PKTHLN_PTR work, u8 *seq)
{
	PKTHLN_FUNC func;
	if (work->EventSeq.FuncTbl == NULL){
		//シーケンスシフト
		PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_EVT_CALL_END);
		return FALSE;
	}

	//アクティブシーケンスがフレームシーケンスの場合は、イベントシーケンスに変更する
	if (work->SeqCnt.ActiveSeqData == &work->FrameSeq){
		OS_Printf("アクティブシーケンスをイベントシーケンスにセット\n");
		work->SeqCnt.ActiveSeqData = &work->EventSeq;
		work->SeqCnt.ChgReqFlg = 0;
	}

	//シーケンスの実行
	func = work->EventSeq.FuncTbl[work->EventSeq.TblIdx];
	if ( func(work, &work->EventSeq.SubSeq) ){
		//描画を禁止
		PTFrame_SetDraw(work, FALSE);
		//アクティブシーケンスをフレームシーケンスに戻す
		work->SeqCnt.ActiveSeqData = &work->FrameSeq;
		work->SeqCnt.ChgReqFlg = 0;
		//シーケンスシフト
		PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_EVT_CALL_END);
	}
	return FALSE;
}

//----------------------------------------------------------------------------
/**
 *	@brief 競技タイトルコール終了
 *
 *	@param	work		ワーク
 *	@param	*seq		シーケンサ
 *
 *	@return	BOOL		FALSE
 */
//-----------------------------------------------------------------------------
static BOOL FrameFuncEvtCallEnd(PKTHLN_PTR work, u8 *seq)
{
	OS_Printf("タイトルコール終了\n");
	work->FuncTbl->EndFunc(work, NULL);
	//イベントワークの解放忘れをチェック
	GF_ASSERT_MSG(work->EventWork == NULL,"イベントワークの解放忘れ\n");
	//フレームワーク描画関数を描画関数としてセット
//	work->PokethlonDraw = FrameDraw;

#ifdef PM_DEBUG
	//ヒープ調べる
	if(PkthHeap != sys_GetHeapFreeSize(HEAPID_POKETHLON)){
		GF_ASSERT_MSG(0, "PKTH_HEAP SIZE %d < %d\n",
						PkthHeap, sys_GetHeapFreeSize(HEAPID_POKETHLON));
	}
#endif
	//------------------------------------------------------------
	//シーケンスシフト
	//------------------------------------------------------------

#ifdef DEBUG_ONLY_FOR_genya_hosaka
	// DEBUGボタンを押していると無限ループ！
	if( (sys.cont & PAD_BUTTON_DEBUG) && (sys.cont & PAD_BUTTON_L) )
	{
		WIPE_SetBrightnessFadeOut( WIPE_FADE_BLACK ); // 黒フェードアウト状態に
		PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_OPENING_SET);
		HOSAKA_PRINT("開会式をもう一度再生！\n");
	}
	else
	if( sys.cont & PAD_BUTTON_DEBUG )
	{
		WIPE_SetBrightnessFadeOut( WIPE_FADE_WHITE ); // 白フェードアウト状態に
		PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_ENDING_SET);
	}
	else
#endif
	{
		PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_EVENT_SET);
	}

	return FALSE;
}

//----------------------------------------------------------------------------
/**
 *	@brief	イベントセット
 *
 *	@param	work		ワーク
 *	@param	*seq		シーケンサ
 *
 *	@return	BOOL		FALSE
 */
//-----------------------------------------------------------------------------
static BOOL FrameFunc_EventSet(PKTHLN_PTR work, u8 *seq)
{
	u8 code;
	//種目コード取得
	code = work->CommCmnData.EventNo[work->EventCounter];
	//ペンアクター使用変数初期化
	work->PenNum = 0;
	//レコードチェック初期化
	work->CheckRecord = REC_NO_DATA;
	//SE用テンポラリ初期化
	work->SeTmpSec = 0;
	//レコードコールバック関数登録クリア
	work->RecordCallBack = NULL;

	//通信データクリア
	PTFrame_ClearEvtComCmnData(work);

	//ファンクションテーブルのセット
	work->FuncTbl = ProcFuncTbl[code];
	work->SubSeq = 0;

	OS_Printf("%d競技目::コード%d\n",work->EventCounter+1, code);
	{
		const PKTHLN_FUNC *pkthlon_func = EventTable[code];
		//シーケンス関数テーブルのセット
		InitSeqData(pkthlon_func, &work->EventSeq);
	}
	//描画関数のスイッチ
//	work->PokethlonDraw = EventDraw;
	//シーケンスシフト
	PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_EVENT_INIT);
	return FALSE;
}

//----------------------------------------------------------------------------
/**
 *	@brief	ポケスロンイベント初期化
 *
 *	@param	work		ワーク
 *	@param	*seq		シーケンサ
 *
 *	@return	BOOL		FALSE
 */
//-----------------------------------------------------------------------------
static BOOL FrameFunc_EventInit(PKTHLN_PTR work, u8 *seq)
{
	if ( FuncInit(work) ){
		//競技メイン中の通信データサイズを設定
		{
			COMM_EVENT_COMMON_DATA * data;
			data = PTFrame_GetEvtComCmnData(work);
			data->SendData.Share = 0;
			data->SendShareData.Share = 1;

			//38バイト制限有効
			PKTHLN_CommPack_SetSizeBind( PTFrame_GetCommPackPtr(work), 1 );
		}
		//同期を取る
		PTFrame_SetSynchroID(work, PKTHLN_SYNC_ID_INIT_WAIT);

		//BGMセット
		if (work->EventCounter == work->EventMax-1){
			//サウンドシーン変更
			Snd_SceneSet( SND_SCENE_DUMMY );
			Snd_DataSetByScene( SND_SCENE_THLON, SEQ_GS_PT_GAMEF, 0 );
		}else{
			//サウンドシーン変更
			Snd_SceneSet( SND_SCENE_DUMMY );
			Snd_DataSetByScene( SND_SCENE_THLON, SEQ_GS_PT_GAME, 0 );
		}

		Snd_PlayerPause( PLAYER_BGM, TRUE );
		//シーケンスシフト
		PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_EVENT_SHARE_DATA);

		OS_Printf("競技初期化終了。同期待ち\n");
		GF_ASSERT(sys_CheckHeapSafe( HEAPID_POKETHLON));
	}
	return FALSE;
}
#if 0
//----------------------------------------------------------------------------
/**
 *	@brief	コマンドチェンジ
 *
 *	@param	work		ワーク
 *	@param	*seq		シーケンサ
 *
 *	@return	BOOL		FALSE
 */
//-----------------------------------------------------------------------------
static BOOL FrameFunc_ChangeEventCommand(PKTHLN_PTR work, u8 *seq)
{
	//コマンドリスト変更
	PKTHLN_CommPack_CommandChange( work->CommPackPtr,
							PKTHLN_Test_GetCommCommandTbl(),
							PKTHLN_Test_GetCommCommandTblNum(),
							work);
	//同期を取る
	PTFrame_SetSynchroID(work, PKTHLN_SYNC_ID_COMMAND_CHANGE_WAIT);

	//シーケンスシフト
	PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_EVENT_MAIN);
	return FALSE;
}
#endif
//----------------------------------------------------------------------------
/**
 *	@brief	アプリ内通信共有データの配信と受け取り待ち
 *
 *	@param	work		ワーク
 *	@param	*seq		シーケンサ
 *
 *	@return	BOOL		FALSE
 */
//-----------------------------------------------------------------------------
static BOOL FrameFunc_EventShareData(PKTHLN_PTR work, u8 *seq)
{
	BOOL rc;
	//アプリ内共有データが・・・
	if( work->EvtComCmnData.EvShareData.Valid ){		//あって、通信で共有する必要あり
		OS_Printf("共有データあり\n");
		if (PTFrameGetCurrentID(work) == COMM_PARENT_ID){		//親なので、子機でデータ送信
			rc = PKTHLN_CommPack_CommSendHugeData( COMM_PKTHLN_EVT_SHARE_DATA,
						work->EvtComCmnData.EvShareData.SendDataPtr, work->EvtComCmnData.EvShareData.Size,
						work->CommPackPtr );
			if (rc){
				//コールバック待ちシーケンスへ
				PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_CALLBACK_WAIT);
			}else{
				OS_Printf("親：アプリ内データ送信失敗\n");
			}
		}else{		//子機なので、受け取り待ち
			//コールバック待ちシーケンスへ
			PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_CALLBACK_WAIT);
		}
	}else{		//なし
		OS_Printf("共有データなし\n");
		//シーケンスシフト
		PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_EVENT_MAIN);
	}
	return FALSE;
}

//----------------------------------------------------------------------------
/**
 *	@brief	ポケスロンイベント
 *
 *	@param	work		ワーク
 *	@param	*seq		シーケンサ
 *
 *	@return	BOOL		FALSE
 */
//-----------------------------------------------------------------------------
static BOOL FrameFunc_EventMain(PKTHLN_PTR work, u8 *seq)
{
	PKTHLN_FUNC func;
	if (work->EventSeq.FuncTbl == NULL){
		//シーケンスシフト
		PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_EVENT_NEXT);
		return FALSE;
	}

	//アクティブシーケンスがフレームシーケンスの場合は、イベントシーケンスに変更する
	if (work->SeqCnt.ActiveSeqData == &work->FrameSeq){
		OS_Printf("アクティブシーケンスをイベントシーケンスにセット\n");
		work->SeqCnt.ActiveSeqData = &work->EventSeq;
		work->SeqCnt.ChgReqFlg = 0;
	}

	//シーケンスの実行
	func = work->EventSeq.FuncTbl[work->EventSeq.TblIdx];
	if ( func(work, &work->EventSeq.SubSeq) ){
		//描画を禁止
		PTFrame_SetDraw(work, FALSE);
		//アクティブシーケンスをフレームシーケンスに戻す
		work->SeqCnt.ActiveSeqData = &work->FrameSeq;
		work->SeqCnt.ChgReqFlg = 0;
		//同期を取る
		PTFrame_SetSynchroID(work, PKTHLN_SYNC_ID_EVENT_END_WAIT);
		//シーケンスシフト
		PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_EVENT_RSLT_SHARE_START);
	}else{
		// 競技中は常に転送
		if ( PTFrameGetCurrentID(work) == COMM_PARENT_ID ){		//親
			PKTHLN_CommPack_CommSendData( COMM_PKTHLN_EVT_CMN_DATA, &work->EvtComCmnData.SendShareData,
					CommPkthlnGetEvtCmnDataSize(), work->CommPackPtr );
			{
				//親データは直接レシーバにセット
				PTHLN_COMM_DATA *child;
				PTHLN_COMM_DATA *child_rec;
				child_rec = PKTHLN_CommPack_GetData(&work->EvtComCmnData.ReciveData[0]);
				child = PKTHLN_CommPack_GetData(&work->EvtComCmnData.SendData);
				(*child_rec) = (*child);
			}
		}else{		//子
			PKTHLN_CommPack_CommSendData( COMM_PKTHLN_EVT_CMN_DATA, &work->EvtComCmnData.SendData,
					CommPkthlnGetEvtCmnDataSize(), work->CommPackPtr );
		}
	}
	return FALSE;
}

//----------------------------------------------------------------------------
/**
 *	@brief	ポケスロンイベント結果共有開始
 *
 *	@param	work		ワーク
 *	@param	*seq		シーケンサ
 *
 *	@return	BOOL		FALSE
 */
//-----------------------------------------------------------------------------
static BOOL FrameFunc_EventRsltShareStart(PKTHLN_PTR work, u8 *seq)
{
	OS_Printf("通信データを一度クリア\n");
	PTFrame_ClearEvtComCmnData(work);
	//シーケンスシフト
	PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_EVENT_RESULT_SHARE);
	return FALSE;
}

//----------------------------------------------------------------------------
/**
 *	@brief	ポケスロンイベント結果共有
 *
 *	@param	work		ワーク
 *	@param	*seq		シーケンサ
 *
 *	@return	BOOL		FALSE
 */
//-----------------------------------------------------------------------------
static BOOL FrameFunc_EventResultShare(PKTHLN_PTR work, u8 *seq)
{
	BOOL rc;
	EVENT_RESULT_DATA *data;
	OS_Printf("競技結果の共有\n");

	rc = FALSE;

	if (work->FuncTbl->ResultSend){	//各子機が、親に結果を送信
		data = PKTHLN_CommPack_GetData(&work->EvtComCmnData.SendData);
		//コピー
		(*data) = work->RsltDataOrg[ PTFrameGetCurrentID(work) ];
		//結果を送信
		rc = PKTHLN_CommPack_CommSendData( COMM_PKTHLN_EVT_RSLT_ADD_UP, &work->EvtComCmnData.SendData,
					CommPkthlnGetEvtCmnDataSize(), work->CommPackPtr );

		//親の場合NPCデータのコピー
		if ( rc && (PTFrameGetCurrentID(work) == COMM_PARENT_ID) ){
			int i;
			u8 *byte;
			u8 *adr;
			int size = PTFrame_GetEvtResultDataSize(work);
			for(i=PTFrame_GetPlayerNum(work);i<ENTRY_MEMBER_NUM_MAX;i++){
				//共有データの書き換え位置取得
				byte = PKTHLN_CommPack_GetData(&work->EvtComCmnData.SendShareData);
				adr = &byte[i*size];
				memcpy( adr, &work->RsltDataOrg[i], size );
			}
		}
	}else{	//アプリ結果を返す必要がないのであれば、親以外は、結果データ待ちにする
		if (PTFrameGetCurrentID(work) == COMM_PARENT_ID){
			rc = AddUpParentOnly(work);
		}else{
			//ここには子機がくる
			rc = TRUE;
		}
	}

	if (rc){
		//コールバック待ちシーケンスへ
		PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_CALLBACK_WAIT);
	}else{
		OS_Printf("競技結果を送信失敗\n");
	}
	return FALSE;
}

//----------------------------------------------------------------------------
/**
 *	@brief	親だけが来るシーケンス　リザルトデータを全員にシェア
 *
 *	@param	work		ワーク
 *	@param	*seq		シーケンサ
 *
 *	@return	BOOL		FALSE
 */
//-----------------------------------------------------------------------------
static BOOL FrameFunc_ParentShareRsltData(PKTHLN_PTR work, u8 *seq)
{
	BOOL rc;
	COMM_EVENT_COMMON_DATA *data = PTFrame_GetEvtComCmnData(work);
	//集まったら全員に集計データを送信
	OS_Printf("親が結果データを送信\n");
	rc = PKTHLN_CommPack_CommSendData( COMM_PKTHLN_ALL_RESULT,
			&data->SendShareData, CommPkthlnGetEvtCmnDataSize(),
			PTFrame_GetCommPackPtr(work) );
	if (rc){
		//コールバック待ちシーケンスへ
		PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_CALLBACK_WAIT);
	}else{
		OS_Printf("親：結果データを送信失敗\n");
	}
	return FALSE;
}


//----------------------------------------------------------------------------
/**
 *	@brief	ポケスロンイベント結果データ作成
 *
 *	@param	work		ワーク
 *	@param	*seq		シーケンサ
 *
 *	@return	BOOL		FALSE
 */
//-----------------------------------------------------------------------------
static BOOL FrameFunc_EventResultMake(PKTHLN_PTR work, u8 *seq)
{
	int i;
	EVENT_RESULT_DATA_ALL *all_data;
	all_data = PKTHLN_CommPack_GetData(&work->EvtComCmnData.ReciveShareData);
	for(i=0;i<4;i++){
		OS_Printf("%d:result = %d\n", i, all_data->All[i].Data);
	}

	work->RsltDataAll = (*all_data);

	//共有した結果データをリザルト構造体に格納
	if (work->FuncTbl->ResultFunc != NULL){
		work->FuncTbl->ResultFunc(work, NULL);
	}
	//セーブデータ格納のためテンポラリデータ作成
	SetResultTmpData(work, work->EventCounter);
	//シーケンスシフト
	PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_EVENT_END);
	return FALSE;
}

//----------------------------------------------------------------------------
/**
 *	@brief	ポケスロンイベント終了
 *
 *	@param	work		ワーク
 *	@param	*seq		シーケンサ
 *
 *	@return	BOOL		FALSE
 */
//-----------------------------------------------------------------------------
static BOOL FrameFunc_EventEnd(PKTHLN_PTR work, u8 *seq)
{
	OS_Printf("競技終了\n");
	GF_ASSERT(sys_CheckHeapSafe( HEAPID_POKETHLON));
	work->FuncTbl->EndFunc(work, NULL);

	//イベントワークの解放忘れをチェック
	GF_ASSERT_MSG(work->EventWork == NULL,"イベントワークの解放忘れ\n");

	//フレームワーク描画関数を描画関数としてセット
//	work->PokethlonDraw = FrameDraw;
#ifdef PM_DEBUG
	//ヒープ調べる
	if(PkthHeap != sys_GetHeapFreeSize(HEAPID_POKETHLON)){
		GF_ASSERT_MSG(0, "PKTH_HEAP SIZE %d < %d\n",
						PkthHeap, sys_GetHeapFreeSize(HEAPID_POKETHLON));
	}
#endif
	if (work->EventCounter < work->EventMax){
		if (work->FuncTbl->ResultFunc != NULL){
			//シーケンスシフト
			PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_RESULT_SET);
		}else{
			//シーケンスシフト
			PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_EVENT_NEXT);
		}
	}
	else{
		OS_Printf("ここにはきませんが。競技目終了。アクション集計へ\n");
		++work->EventCounter;
		//シーケンスシフト
		PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_SEND_EVT_ACT_DATA);
	}
	return FALSE;
}

//----------------------------------------------------------------------------
/**
 *	@brief	次の競技判定
 *
 *	@param	work		ワーク
 *	@param	*seq		シーケンサ
 *
 *	@return	BOOL		FALSE
 */
//-----------------------------------------------------------------------------
static BOOL FrameFunc_EventNext(PKTHLN_PTR work, u8 *seq)
{
	OS_Printf("次競技判定\n");

	//種目カウンターのインクリメント
	++work->EventCounter;
	if (work->EventCounter >= work->EventMax){
#ifdef DEBUG_INFINIT
		work->EventCounter = 0;
		//次の競技へシーケンスシフト
		PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_EVT_CALL_SET);
#else
		//アクションデータ集計へシーケンスシフト
		PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_SEND_EVT_ACT_DATA);
#endif
	}else{
#ifdef PM_DEBUG
		OS_Printf("競技終了時のアクションポイント\n");
		PrintActPoint(work);
#endif
		//次の競技へシーケンスシフト
		PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_EVT_CALL_SET);
	}
	return FALSE;
}

//----------------------------------------------------------------------------
/**
 *	@brief	結果発表セット
 *
 *	@param	work		ワーク
 *	@param	*seq		シーケンサ
 *
 *	@return	BOOL		FALSE
 */
//-----------------------------------------------------------------------------
static BOOL FrameFuncResultSet(PKTHLN_PTR work, u8 *seq)
{
	OS_Printf("結果発表セット\n");
	//ファンクションテーブルのセット
	work->FuncTbl = &PE_ResultFuncTbl;
	work->SubSeq = 0;
	//シーケンス関数テーブルのセット
	InitSeqData(&ResultFuncTbl[0], &work->EventSeq);
	//描画関数のスイッチ
//	work->PokethlonDraw = EventDraw;
	//シーケンスシフト
	PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_RESULT_INIT);
	return FALSE;
}

//----------------------------------------------------------------------------
/**
 *	@brief	結果発表初期化
 *
 *	@param	work		ワーク
 *	@param	*seq		シーケンサ
 *
 *	@return	BOOL		FALSE
 */
//-----------------------------------------------------------------------------
static BOOL FrameFuncResultInit(PKTHLN_PTR work, u8 *seq)
{
	OS_Printf("結果発表初期化\n");
	if ( FuncInit(work) ){
		//通信データサイズを設定
		{
			COMM_EVENT_COMMON_DATA * data;
			data = PTFrame_GetEvtComCmnData(work);
			data->SendData.Share = 0;
			data->SendShareData.Share = 1;

			//38バイト制限有効
			PKTHLN_CommPack_SetSizeBind( PTFrame_GetCommPackPtr(work), 1 );
		}
		//同期を取って次のシーケンスで結果発表メイン
		PTFrame_SetSynchroID(work, PKTHLN_SYNC_ID_RESULT_INIT_WAIT);
		//シーケンスシフト
		PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_RESULT_MAIN);
	}
	return FALSE;
}

//----------------------------------------------------------------------------
/**
 *	@brief	結果発表メイン
 *
 *	@param	work		ワーク
 *	@param	*seq		シーケンサ
 *
 *	@return	BOOL		FALSE
 */
//-----------------------------------------------------------------------------
static BOOL FrameFuncResultMain(PKTHLN_PTR work, u8 *seq)
{
	PKTHLN_FUNC func;
	if (work->EventSeq.FuncTbl == NULL){
		//シーケンスシフト
		PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_RESULT_END);
		return FALSE;
	}

	//アクティブシーケンスがフレームシーケンスの場合は、イベントシーケンスに変更する
	if (work->SeqCnt.ActiveSeqData == &work->FrameSeq){
		OS_Printf("アクティブシーケンスをイベントシーケンスにセット\n");
		work->SeqCnt.ActiveSeqData = &work->EventSeq;
		work->SeqCnt.ChgReqFlg = 0;
	}

	//シーケンスの実行
	func = work->EventSeq.FuncTbl[work->EventSeq.TblIdx];
	if ( func(work, &work->EventSeq.SubSeq) ){
		//描画を禁止
		PTFrame_SetDraw(work, FALSE);
		//アクティブシーケンスをフレームシーケンスに戻す
		work->SeqCnt.ActiveSeqData = &work->FrameSeq;
		work->SeqCnt.ChgReqFlg = 0;
		//シーケンスシフト
		PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_RESULT_END);
	}else{
		// 競技中は常に転送
		if ( PTFrameGetCurrentID(work) == COMM_PARENT_ID ){		//親
			PKTHLN_CommPack_CommSendData( COMM_PKTHLN_EVT_CMN_DATA, &work->EvtComCmnData.SendShareData,
					CommPkthlnGetEvtCmnDataSize(), work->CommPackPtr );
			{
				//親データは直接レシーバにセット
				PTHLN_COMM_DATA *child;
				PTHLN_COMM_DATA *child_rec;
				child_rec = PKTHLN_CommPack_GetData(&work->EvtComCmnData.ReciveData[0]);
				child = PKTHLN_CommPack_GetData(&work->EvtComCmnData.SendData);
				(*child_rec) = (*child);
			}
		}else{		//子
			PKTHLN_CommPack_CommSendData( COMM_PKTHLN_EVT_CMN_DATA, &work->EvtComCmnData.SendData,
					CommPkthlnGetEvtCmnDataSize(), work->CommPackPtr );
		}
	}
	return FALSE;
}

//----------------------------------------------------------------------------
/**
 *	@brief 結果発表終了
 *
 *	@param	work		ワーク
 *	@param	*seq		シーケンサ
 *
 *	@return	BOOL		FALSE
 */
//-----------------------------------------------------------------------------
static BOOL FrameFuncResultEnd(PKTHLN_PTR work, u8 *seq)
{
	OS_Printf("結果発表終了\n");
	work->FuncTbl->EndFunc(work, NULL);
	//イベントワークの解放忘れをチェック
	GF_ASSERT_MSG(work->EventWork == NULL,"イベントワークの解放忘れ\n");
	//フレームワーク描画関数を描画関数としてセット
//	work->PokethlonDraw = FrameDraw;
#ifdef PM_DEBUG
	//ヒープ調べる
	if(PkthHeap != sys_GetHeapFreeSize(HEAPID_POKETHLON)){
		GF_ASSERT_MSG(0, "PKTH_HEAP SIZE %d < %d\n",
						PkthHeap, sys_GetHeapFreeSize(HEAPID_POKETHLON));
	}
#endif
	//シーケンスシフト
	PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_EVENT_NEXT);
	return FALSE;
}

//----------------------------------------------------------------------------
/**
 *	@brief	閉会式セット
 *
 *	@param	work		ワーク
 *	@param	*seq		シーケンサ
 *
 *	@return	BOOL		FALSE
 */
//-----------------------------------------------------------------------------
static BOOL FrameFuncEndingSet(PKTHLN_PTR work, u8 *seq)
{
	//通信データクリア
	PTFrame_ClearEvtComCmnData(work);

	//ファンクションテーブルのセット
	work->FuncTbl = &PE_EndingFuncTbl;
	work->SubSeq = 0;
	//シーケンス関数テーブルのセット
	InitSeqData(&EndingFuncTbl[0], &work->EventSeq);
	//描画関数のスイッチ
//	work->PokethlonDraw = EventDraw;
	//シーケンスシフト
	PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_ENDING_INIT);
	return FALSE;
}

//----------------------------------------------------------------------------
/**
 *	@brief 閉会式初期化
 *
 *	@param	work		ワーク
 *	@param	*seq		シーケンサ
 *
 *	@return	BOOL		FALSE
 */
//-----------------------------------------------------------------------------
static BOOL FrameFuncEndingInit(PKTHLN_PTR work, u8 *seq)
{
	OS_Printf("閉会式初期化\n");
	if ( FuncInit(work) ){
		//通信データサイズを設定
		{
			COMM_EVENT_COMMON_DATA * data;
			data = PTFrame_GetEvtComCmnData(work);
			data->SendData.Share = 0;
			data->SendShareData.Share = 1;

			//38バイト制限有効
			PKTHLN_CommPack_SetSizeBind( PTFrame_GetCommPackPtr(work), 1 );
		}
		//同期を取って次のシーケンスで開会式メイン
		PTFrame_SetSynchroID(work, PKTHLN_SYNC_ID_ENDING_INIT_WAIT);
		//シーケンスシフト
		PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_ENDING_MAIN);
		//サウンドシーン変更
		Snd_SceneSet( SND_SCENE_DUMMY );
		Snd_DataSetByScene( SND_SCENE_THLON_OPED, SEQ_GS_PT_END, 0 );
	}
	return FALSE;
}

//----------------------------------------------------------------------------
/**
 *	@brief	閉会式メイン
 *
 *	@param	work		ワーク
 *	@param	*seq		シーケンサ
 *
 *	@return	BOOL		FALSE
 */
//-----------------------------------------------------------------------------
static BOOL FrameFuncEndingMain(PKTHLN_PTR work, u8 *seq)
{
	PKTHLN_FUNC func;
	if (work->EventSeq.FuncTbl == NULL){
		//シーケンスシフト
		PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_ENDING_END);
		return FALSE;
	}

	//アクティブシーケンスがフレームシーケンスの場合は、イベントシーケンスに変更する
	if (work->SeqCnt.ActiveSeqData == &work->FrameSeq){
		OS_Printf("アクティブシーケンスをイベントシーケンスにセット\n");
		work->SeqCnt.ActiveSeqData = &work->EventSeq;
		work->SeqCnt.ChgReqFlg = 0;
	}

	//シーケンスの実行
	func = work->EventSeq.FuncTbl[work->EventSeq.TblIdx];
	if ( func(work, &work->EventSeq.SubSeq) ){
		//描画を禁止
		PTFrame_SetDraw(work, FALSE);
		//アクティブシーケンスをフレームシーケンスに戻す
		work->SeqCnt.ActiveSeqData = &work->FrameSeq;
		work->SeqCnt.ChgReqFlg = 0;
		//シーケンスシフト
		PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_ENDING_END);
	}else{
		// 競技中は常に転送
		if ( PTFrameGetCurrentID(work) == COMM_PARENT_ID ){		//親
			PKTHLN_CommPack_CommSendData( COMM_PKTHLN_EVT_CMN_DATA, &work->EvtComCmnData.SendShareData,
					CommPkthlnGetEvtCmnDataSize(), work->CommPackPtr );
			{
				//親データは直接レシーバにセット
				PTHLN_COMM_DATA *child;
				PTHLN_COMM_DATA *child_rec;
				child_rec = PKTHLN_CommPack_GetData(&work->EvtComCmnData.ReciveData[0]);
				child = PKTHLN_CommPack_GetData(&work->EvtComCmnData.SendData);
				(*child_rec) = (*child);
			}
		}else{		//子
			PKTHLN_CommPack_CommSendData( COMM_PKTHLN_EVT_CMN_DATA, &work->EvtComCmnData.SendData,
					CommPkthlnGetEvtCmnDataSize(), work->CommPackPtr );
		}
	}

	return FALSE;
}

//----------------------------------------------------------------------------
/**
 *	@brief	閉会式終了
 *
 *	@param	work		ワーク
 *	@param	*seq		シーケンサ
 *
 *	@return	BOOL		FALSE
 */
//-----------------------------------------------------------------------------
static BOOL FrameFuncEndingEnd(PKTHLN_PTR work, u8 *seq)
{
	int all_juice_size;
	int one_juice_size;
	work->FuncTbl->EndFunc(work, NULL);
	//イベントワークの解放忘れをチェック
	GF_ASSERT_MSG(work->EventWork == NULL,"イベントワークの解放忘れ\n");
	//フレームワーク描画関数を描画関数としてセット
//	work->PokethlonDraw = FrameDraw;
#ifdef PM_DEBUG
	//ヒープ調べる
	if(PkthHeap != sys_GetHeapFreeSize(HEAPID_POKETHLON)){
		GF_ASSERT_MSG(0, "PKTH_HEAP SIZE %d < %d\n",
						PkthHeap, sys_GetHeapFreeSize(HEAPID_POKETHLON));
	}
#endif

	//ジュースデータ非通信でもアロケーションはしておく
	{
		BONGURI_SAVE* bong_sv = SaveData_GetBonguriSave(work->LinkData.Header->SaveData);
		MYSTATUS* my_status = SaveData_GetMyStatus(work->LinkData.Header->SaveData);
		const PKTH_RNK_DATA* rank = PkthlnSv_GetRnkDataCnst(PkthlnSv_GetSaveData(work->LinkData.Header->SaveData));

		one_juice_size = BonguriSave_GetBongJuiceCommWorkSize();
		all_juice_size =  one_juice_size* ENTRY_MEMBER_NUM_MAX;
		//ワークアロケーション
		work->AllJuiceData = sys_AllocMemoryLo(work->HeapID, all_juice_size);
		memset(work->AllJuiceData, 0, all_juice_size);
		//自分のジュースデータを取得
		work->JuiceData = BongSave_BongJuiceCommDataAlloc(bong_sv, my_status, rank->FunNum,work->HeapID);
	}

	//通信時はジュース通信へシフト
	if (work->LinkData.Header->GameType == PKTHLN_GAME_COMM){
		//※このすぐ上で、ジュース通信データのメモリアロケーションしたので、通信同期を取る
		//とっておかないと、親機のアロケーションが済んでいないのに、子機が送信してきた場合、親機の通信コールバックで不正アクセスになる。
		PTFrame_SetSynchroID(work, PKTHLN_SYNC_ID_JUICE_ALLOC_WAIT);
		//↑ジュースデータ送信前に全員がジュースデータのアロケーションが済んでいることを保障する
		//シーケンスシフト
		PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_SEND_MY_JUICEDATA);
	}else{
		//シーケンスシフト
		PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_END);
	}
	return FALSE;
}

//----------------------------------------------------------------------------
/**
 *	@brief	ポケスロン競技アクションデータを親に送信
 *
 *	@param	work		ワーク
 *	@param	*seq		シーケンサ
 *
 *	@return	BOOL		FALSE
 */
//-----------------------------------------------------------------------------
static BOOL FrameFunc_SendEvtActData(PKTHLN_PTR work, u8 *seq)
{
	BOOL rc;
	u8 net_id;
	OS_Printf("競技アクションデータ親に送信\n");
	net_id = PTFrameGetCurrentID(work);
#ifdef PM_DEBUG
	OS_Printf("自分のローカルアクションデータをプリント\n");
	PrintLocalActPoint(work);
#endif
	//競技内アクションデータを親に転送
	rc = PKTHLN_CommPack_CommSendHugeData( COMM_PKTHLN_SEND_EVT_ACT_DATA,
				&(work->EvtActionTmp[0]), CommPkthlnGetEvtActionDataSize(),
				work->CommPackPtr );

	if (rc){
		//シーケンスシフト
		PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_CALLBACK_WAIT);
	}else{
		OS_Printf("競技内アクションデータを親に送信失敗\n");
	}
	return FALSE;
}

//----------------------------------------------------------------------------
/**
 *	@brief	親だけが来るシーケンス　アクションデータを全員にシェア
 *
 *	@param	work		ワーク
 *	@param	*seq		シーケンサ
 *
 *	@return	BOOL		FALSE
 */
//-----------------------------------------------------------------------------
static BOOL FrameFunc_ParentShareActData(PKTHLN_PTR work, u8 *seq)
{
	BOOL rc;
	void *data = PTFrame_GetEvtActDataPtr(work, 0);
	OS_Printf("親がアクションデータを送信\n");
	//集まったら全員に4人分集計データを送信(格納バッファを転送元バッファとして使用する)
	rc = PKTHLN_CommPack_CommSendHugeData( COMM_PKTHLN_SHARE_EVT_ACT_DATA,
				data, CommPkthlnGetAllEvtActionDataSize(),
				PTFrame_GetCommPackPtr(work) );

	if (rc){
		//コールバック待ちシーケンスへ
		PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_CALLBACK_WAIT);
	}else{
		OS_Printf("親：アクションデータ送信失敗\n");
	}
	return FALSE;
}

//----------------------------------------------------------------------------
/**
 *	@brief	ジュースデータを親に送信
 *
 *	@param	work		ワーク
 *	@param	*seq		シーケンサ
 *
 *	@return	BOOL		FALSE
 */
//-----------------------------------------------------------------------------
static BOOL FrameFunc_SendMyJuiceDat(PKTHLN_PTR work, u8 *seq)
{
	BOOL rc;
	int one_juice_size = BonguriSave_GetBongJuiceCommWorkSize();
	//ジュースデータを親に転送
	rc = PKTHLN_CommPack_CommSendHugeData( COMM_PKTHLN_SEND_JUICE_DATA,
			work->JuiceData, one_juice_size,
			work->CommPackPtr );
	if (rc){
		//シーケンスシフト
		PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_CALLBACK_WAIT);
	}else{
		OS_Printf("ジュースデータ親に送信失敗\n");
	}
	return FALSE;
}

//----------------------------------------------------------------------------
/**
 *	@brief	ジュースデータをセーブに反映
 *
 *	@param	work		ワーク
 *	@param	*seq		シーケンサ
 *
 *	@return	BOOL		FALSE
 */
//-----------------------------------------------------------------------------
static BOOL FrameFunc_SetJuiceDatToSv(PKTHLN_PTR work, u8 *seq)
{
	BONGURI_SAVE* bong_sv = SaveData_GetBonguriSave(work->LinkData.Header->SaveData);
	OS_Printf("ジュースデータをセーブに反映\n");
	BongSave_BongJuiceCommDataSet( bong_sv, work->AllJuiceData, PTFrame_GetPlayerNum(work),	CommGetCurrentID());

	GF_ASSERT(sys_CheckHeapSafe( HEAPID_POKETHLON));
	//シーケンスシフト
	PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_END);
	return FALSE;
}

#if 0
//----------------------------------------------------------------------------
/**
 *	@brief	親だけが来るシーケンス　ジュースデータを全員にシェア
 *
 *	@param	work		ワーク
 *	@param	*seq		シーケンサ
 *
 *	@return	BOOL		FALSE
 */
//-----------------------------------------------------------------------------
static BOOL FrameFunc_ParentShareJcData(PKTHLN_PTR work, u8 *seq)
{
	BOOL rc;
	void *data = PTFrame_GetAllJuiceDataAdr(work, 0);
	OS_Printf("親がジュースデータを送信\n");

	//集まったら全員に4人分集計データを送信(格納バッファを転送元バッファとして使用する)
	rc = PKTHLN_CommPack_CommSendHugeData( COMM_PKTHLN_SHARE_JUICE_DATA,
				data, CommPkthlnGetAllJuiceDataSize(),
				PTFrame_GetCommPackPtr(work) );

	if (rc){
		//コールバック待ちシーケンスへ
		PTFrame_SetNextFuncTblIdx(work, FRAME_SEQ_CALLBACK_WAIT);
	}else{
		OS_Printf("親：ジュースデータ送信失敗\n");
	}
	return FALSE;
}
#endif

//----------------------------------------------------------------------------
/**
 *	@brief	ポケスロン終了
 *
 *	@param	work		ワーク
 *	@param	*seq		シーケンサ
 *
 *	@return	BOOL		TRUE
 */
//-----------------------------------------------------------------------------
static BOOL FrameFunc_End(PKTHLN_PTR work, u8 *seq)
{
	GF_ASSERT(sys_CheckHeapSafe( HEAPID_POKETHLON));
	if (!work->LinkData.Header->RetExit){
		SetSaveData(work);
	}

	OS_Printf("ポケスロン終了\n");
	return TRUE;
}

//----------------------------------------------------------------------------
/**
 *	@brief	コールバック待ち
 *
 *	@param	work		ワーク
 *	@param	*seq		シーケンサ
 *
 *	@return	BOOL		FALSE
 */
//-----------------------------------------------------------------------------
static BOOL FrameFunc_CallBackWait(PKTHLN_PTR work, u8 *seq)
{
	return FALSE;
}

//--------------------------------------------------------------------------------------------
/**
 * VBlank関数
 *
 * @param	work		ワーク
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void VBlankFunc( void * work )
{
	GF_BGL_INI *bgl = (GF_BGL_INI *)work;
	// レンダラ共有OAMマネージャVram転送
	REND_OAMTrans();

	//BGL
	GF_BGL_VBlankFunc(bgl);

	DoVramTransferManager();

	OS_SetIrqCheckFlag( OS_IE_V_BLANK );
}

//----------------------------------------------------------------------------
/**
 *	@brief	ポケスロン参加ポケモン集計　（親が直接コール）
 *
 *	@param	work			ポケスロンワーク
 *
 *	@return	BOOL 			送信成功の場合はTRUE
 */
//-----------------------------------------------------------------------------
static BOOL AddUpParentOnly( PKTHLN_PTR work )
{
	BOOL rc;
	int i;
	COMM_EVENT_COMMON_DATA *data = PTFrame_GetEvtComCmnData(work);

	//親判定
	if( PTFrameGetCurrentID(work) != COMM_PARENT_ID ){
		GF_ASSERT(0);
		return FALSE;
	}

	for(i=0;i<ENTRY_MEMBER_NUM_MAX;i++){
		int size;
		u8 *byte;
		u8 *adr;

		size = PTFrame_GetEvtResultDataSize(work);
		//共有データの書き換え位置取得
		byte = PKTHLN_CommPack_GetData(&data->SendShareData);
		adr = &byte[i*size];
		memcpy( adr, &work->RsltDataOrg[i], size );
	}
	OS_Printf("親が結果データを送信\n");
	rc = PKTHLN_CommPack_CommSendData( COMM_PKTHLN_ALL_RESULT,
				&data->SendShareData, CommPkthlnGetEvtCmnDataSize(),
				PTFrame_GetCommPackPtr(work) );
	return rc;
}

//----------------------------------------------------------------------------
/**
 *	@brief	リザルトデータをセーブ用にテンポラリに保存
 *
 *	@param	work			ポケスロンワーク
 *	@param	inEvt			イベントナンバー
 *
 *	@return	none
 */
//-----------------------------------------------------------------------------
static void SetResultTmpData(PKTHLN_PTR work, const u8 inEvt)
{
	u8 i;
	RESULT_DATA *result;
	u8 my_net_id;
	my_net_id = PTFrameGetCurrentID(work);

	for(i=0;i<ENTRY_MEMBER_NUM_MAX;i++){
		result = RSLT_GetResultData(work->Result, i);
		//スコアセット
		work->SvSetData.EvtScore[i][inEvt] = result->Score;
		//競技記録セット
		work->SvSetData.EvtRecord[i][inEvt] = result->RecordOrg;
	}

	//自分の成績を探す
	for (i=0;i<ENTRY_MEMBER_NUM_MAX;i++){
		result = RSLT_GetResultDataPtr(work->Result, i);
		if (result->NetID == my_net_id){
			//発見
			break;
		}
	}

	if (i == ENTRY_MEMBER_NUM_MAX){
		GF_ASSERT(0);
		return;
	}

	//競技で優勝？
	if (result->Rank == 0){
		work->SvSetData.EvtWin[inEvt] = 1;
		work->SvSetData.EvtLose[inEvt] = 0;
	}else{
		RESULT_DATA *lose_result;
		work->SvSetData.EvtWin[inEvt] = 0;
		//最下位検索
		lose_result = RSLT_GetResultDataPtr(work->Result, 3);
		if (lose_result->Rank == result->Rank){
			work->SvSetData.EvtLose[inEvt] = 1;
		}else{
			work->SvSetData.EvtLose[inEvt] = 0;
		}
	}
/**
	//競技で優勝？
	result = RSLT_GetResultDataPtr(work->Result, 0);
	if (result->NetID == my_net_id){
		work->SvSetData.EvtWin[inEvt] = 1;
		work->SvSetData.EvtLose[inEvt] = 0;
	}else{
		work->SvSetData.EvtWin[inEvt] = 0;
		//競技で最下位？
		result = RSLT_GetResultDataPtr(work->Result, 3);
		if (result->NetID == my_net_id){
			work->SvSetData.EvtLose[inEvt] = 1;
		}else{
			work->SvSetData.EvtLose[inEvt] = 0;
		}
	}
*/
}

//---------------------------------------------------------------------------
/**
 * @brief	セーブデータへの反映
 *
 * @param	work		ポケスロンワークポインタ
 *
 * @return	none
 */
//---------------------------------------------------------------------------
static void SetSaveData(PKTHLN_PTR work)
{
	u16 thlon_point;
	PKTHLN_SV_DATA_PTR save = PkthlnSv_GetSaveData(work->LinkData.Header->SaveData);
	PKTHLN_SVSET_DATA *set_data = PTFrame_GetSvSetDataPtr(work);

	EVENTWORK *ev_data = SaveData_GetEventWork(work->LinkData.Header->SaveData);
	//メダル取得
	if (set_data->CrsWin){
		OS_Printf("優勝したのでメダル獲得\n");
		SetMedal(work);

		//イベントフラグチェック
		if ( !EventWork_CheckEventFlag( ev_data, FE_PKTH_MUSEUM03_OPEN ) ){
			if ( CheckOnePokeAllMedal(work) ){
				//フラグ成立
				EventWork_SetEventFlag(	ev_data, FE_PKTH_MUSEUM03_OPEN	);
			}
		}
	}

	//買い物ポイント算出
	thlon_point = set_data->RsltScore;
	//マスターコースの場合はポイントが２倍
	if (work->LinkData.Header->CourseID == CRS_ID_MAS){
		thlon_point *= 2;
	}
	//買い物ポイント加算
	PkthlnSv_AddThlnPoint( save, thlon_point );

	if (work->LinkData.Header->GameType == PKTHLN_GAME_COMM){
		//通信用競技データ
		MakeEvtDataComm(work, PkthlnSv_GetEvtDataComm(save));
	}else{
		//一人用競技ベストレコードのスコア
		MakeBestRecScore(work, PkthlnSv_GetEvtDataAloneCnst(save), PkthlnSv_GetBestRecScore(save));

		if (set_data->CrsWin){
			//一人用コースデータ(優勝したときのみ保存)
			MakeCourseData(work, PkthlnSv_GetCrsDataAlone(save));
			//イベントフラグチェック
			if ( !EventWork_CheckEventFlag( ev_data, FE_PKTH_MUSEUM02_OPEN ) ){
				if ( CheckAloneCrsWin( PkthlnSv_GetCrsDataAlone(save) ) ){
					//フラグ成立
					EventWork_SetEventFlag(	ev_data , FE_PKTH_MUSEUM02_OPEN	);
				}
			}
		}
		//一人用競技データ
		MakeEvtDataAlone(work, PkthlnSv_GetEvtDataAlone(save));
	}

	//ランキングデータ
	MakeRankData(work, PkthlnSv_GetRnkData(save));

	//イベントフラグチェック
	if (work->LinkData.Header->GameType == PKTHLN_GAME_ALONE){
		if ( !EventWork_CheckEventFlag( ev_data, FE_PKTH_MUSEUM04_OPEN ) ){
			//全競技で基準記録を超えたか？
			if ( CheckDefaultRecordUpdate(work) ){
				//フラグ成立
				EventWork_SetEventFlag(	ev_data, FE_PKTH_MUSEUM04_OPEN	);
			}
		}
	}

	//アプリからの返却値をセット
	work->LinkData.Header->RetScore = set_data->RsltScore;
	work->LinkData.Header->RetThlonPt = thlon_point;
	work->LinkData.Header->RetRank = set_data->Rank;
}

//---------------------------------------------------------------------------
/**
 * @brief	一人用コースデータ作成
 *
 * ※一人用だからスコアのネットＩＤは０固定
 *
 * @param	work			ポケスロンワークポインタ
 * @param	outCourseData	コースデータ先頭アドレス
 *
 * @return	none
 */
//---------------------------------------------------------------------------
static void MakeCourseData(PKTHLN_PTR work, PKTH_COURSE * outCourseData)
{
	int i;
	int course_id;
	PKTH_COURSE * course_data;

	course_id = work->LinkData.Header->CourseID;
	course_data = &outCourseData[course_id];

	//セーブされている最高得点を上回ったか？
	if ( work->SvSetData.RsltScore > course_data->MaxScore ){
		POKETHLON_ENTRY_DATA *entry_data;
		//データ書き換え
		course_data->MaxScore = work->SvSetData.RsltScore;
		if ( course_data->MaxScore > PKTHLN_SCORE_MAX ){
			course_data->MaxScore = PKTHLN_SCORE_MAX;
		}
		for(i=0;i<ALONE_EVT_MAX;i++){
			course_data->EvtScore[i] = work->SvSetData.EvtScore[0][i];
			if ( course_data->EvtScore[i] > PKTHLN_SCORE_MAX ){
				course_data->EvtScore[i] = PKTHLN_SCORE_MAX;
			}
		}
		entry_data = PTFrame_GetEntryDataPtrByID(work, PTFrameGetCurrentID(work));
		for(i=0;i<ENTRY_MAX;i++){
			course_data->MonsData[i].MonsNo = entry_data[i].MonsNo;
			course_data->MonsData[i].Form = entry_data[i].Form;
			course_data->MonsData[i].Sex = entry_data[i].Sex;
			course_data->MonsData[i].Rare = entry_data[i].Rare;
			course_data->MonsData[i].Rnd = entry_data[i].PsnlRnd;
		}
	}
}

//---------------------------------------------------------------------------
/**
 * @brief	一人用競技データ作成
 *
 * @param	work		ポケスロンワークポインタ
 * @param	outData		格納バッファ
 *
 * @return	none
 */
//---------------------------------------------------------------------------
static void MakeEvtDataAlone(PKTHLN_PTR work, PKTH_EVT_DATA *outData)
{
	u8 i,j,n;
	u8 evt_code;
	COMP_MODE comp_mode;
	PKTH_EVT_DATA *evt_data;
	SORT_DATA sort_dat_ary[BEST_FIVE];
	for(i=0;i<ALONE_EVT_MAX;i++){
		//種目コード取得
		evt_code = work->CommCmnData.EventNo[i];
		//種目データ取得
		evt_data = &outData[evt_code];
		//参加回数インクリメント
		if (evt_data->EntryNum < ENTRY_NUM_MAX){
			evt_data->EntryNum++;
		}
		//レコード比較方法取得
		comp_mode = SortComp[evt_code];
		//セーブにあるレコード情報をソートデータに書き込む
		for(j=0;j<BEST_FIVE;j++){
			sort_dat_ary[j].Record = evt_data->RcMs[j].Record;
///			sort_dat_ary[j].TypeCode = j;
			for (n=0;n<ENTRY_MAX;n++){
				sort_dat_ary[j].FrmMnsNo[n] = evt_data->RcMs[j].FrmMnsNo[n];
			}
		}
		//自分の記録を見てベストファイブ決定
		{
			u8 my_net_id;
			SORT_DATA sort;
			my_net_id = PTFrameGetCurrentID(work);
			sort.Record = work->SvSetData.EvtRecord[my_net_id][i];
///			sort.TypeCode = NETID_BASE + my_net_id;
			//参加ポケ情報
			{
				u8 my_net_id = PTFrameGetCurrentID(work);
				POKETHLON_ENTRY_DATA *data = work->CommCmnData.PlayerData[my_net_id].EntryData;
				for(n=0;n<ENTRY_MAX;n++){
					sort.FrmMnsNo[n] = (data[n].Form << 10)+data[n].MonsNo;
				}
			}
			//ベストファイブ記録更新処理
			SortData(comp_mode, &sort, sort_dat_ary);
			WriteBestFiveDataAlone(work, evt_data, sort_dat_ary);
		}
	}
}

//---------------------------------------------------------------------------
/**
 * @brief	通信用競技データ作成
 *
 * @param	work		ポケスロンワークポインタ
 * @param	outCommData 格納バッファ
 *
 * @return	none
 */
//---------------------------------------------------------------------------
static void MakeEvtDataComm(PKTHLN_PTR work, PKTH_COMM_EVT_DATA *outCommData)
{
	u8 i,j,n,l;
	u8 evt_code;
	COMP_MODE comp_mode;
	PKTH_COMM_EVT_DATA *comm_evt_data;
	SORT_DATA sort_dat_ary[BEST_FIVE];
	u8 my_net_id = PTFrameGetCurrentID(work);
	//
	for(i=0;i<COMM_EVT_MAX;i++){
		PKTH_EVT_DATA *evt_data;
		//種目コード取得
		evt_code = work->CommCmnData.EventNo[i];
		//種目データ取得
		comm_evt_data = &outCommData[evt_code];
		evt_data = &comm_evt_data->EvtData;
		//参加回数インクリメント
		if (evt_data->EntryNum < ENTRY_NUM_MAX){
			evt_data->EntryNum++;
		}
		//レコード比較方法取得
		comp_mode = SortComp[evt_code];
		//セーブにあるレコード情報をソートデータに書き込む
		for(j=0;j<BEST_FIVE;j++){
			sort_dat_ary[j].Record = evt_data->RcMs[j].Record;
///			sort_dat_ary[j].TypeCode = j;
			for (n=0;n<ENTRY_MAX;n++){
				sort_dat_ary[j].FrmMnsNo[n] = evt_data->RcMs[j].FrmMnsNo[n];
			}
			sort_dat_ary[j].TrID = comm_evt_data->TrData[j].TrID;
			for(l=0;l<BUFLEN_PERSON_NAME;l++){
				sort_dat_ary[j].TrName[l] = comm_evt_data->TrData[j].TrName[l];
			}
			sort_dat_ary[j].CountryCode = comm_evt_data->TrData[j].CountryCode;
		}
		//参加者全員の記録を見てベストファイブ決定
		for (j=0;j<ENTRY_MEMBER_NUM_MAX;j++){
			MYSTATUS *my_status;
			const STRCODE * name;
			SORT_DATA sort;
			u8 idx = (my_net_id+j)%ENTRY_MEMBER_NUM_MAX;
			sort.Record = work->SvSetData.EvtRecord[idx][i];
			//参加ポケ情報
			{
				POKETHLON_ENTRY_DATA *data = work->CommCmnData.PlayerData[idx].EntryData;
				for(n=0;n<ENTRY_MAX;n++){
					sort.FrmMnsNo[n] = (data[n].Form << 10)+data[n].MonsNo;
				}
			}
			my_status = PTFrame_GetMyStatus(work, idx);
			sort.TrID = MyStatus_GetID( my_status );
			name = MyStatus_GetMyName(my_status);
			for(l=0;l<BUFLEN_PERSON_NAME;l++){
				sort.TrName[l] = name[l];
			}
			sort.CountryCode = MyStatus_GetRegionCode(my_status);
			SortData(comp_mode, &sort, sort_dat_ary);
		}
		//ベストファイブ記録更新処理
		WriteBestFiveDataComm(work, comm_evt_data, sort_dat_ary);
	}
}

//---------------------------------------------------------------------------
/**
 * @brief	非通信時ベストレコードのスコア更新
 *
 * @param	work		ポケスロンワークポインタ
 * @param	inEvtData	競技データポインタ
 * @param	outData 格納バッファ
 *
 * @return	none
 */
//---------------------------------------------------------------------------
static void MakeBestRecScore(PKTHLN_PTR work, const PKTH_EVT_DATA *inEvtData, u16 *outData)
{
	u8 i;
	u8 evt_code;
	u16 record;

	for(i=0;i<ALONE_EVT_MAX;i++){
		const PKTH_EVT_DATA *evt_data;
		//種目コード取得
		evt_code = work->CommCmnData.EventNo[i];
		//種目データ取得
		evt_data = &inEvtData[evt_code];
		record = work->SvSetData.EvtRecord[0][i];		//非通信なので必ず添え字は0
		//現在のベスト1のレコードと今回のレコードを比較
		if ( CompVal(evt_data->RcMs[0].Record, record, SortComp[evt_code]) ){		//記録更新
			//スコア更新
			outData[evt_code] = work->SvSetData.EvtScore[0][i];		//非通信なので必ず添え字は0
		}
	}
}

//---------------------------------------------------------------------------
/**
 * @brief	バブルソート
 *
 * @param	inCompMode		比較方法
 * @param	inSortDat		挿入データ
 * @param	ioSortDatAry	ソート配列
 *
 * @return	none
 */
//---------------------------------------------------------------------------
static void SortData(const COMP_MODE inCompMode, const SORT_DATA *inSortDat, SORT_DATA *ioSortDatAry)
{
	int i;
	int base, target;
	//ベストファイブのレコードと今回のレコードを比較
	base = ioSortDatAry[BEST_FIVE-1].Record;
	target = inSortDat->Record;
	if ( CompVal(base, target, inCompMode) ){
		//ベストファイブを上書き
		ioSortDatAry[BEST_FIVE-1] = *inSortDat;
		//バブルソート
		for(i=BEST_FIVE-1;i>0;i--){
			base = ioSortDatAry[i-1].Record;
			target = ioSortDatAry[i].Record;
			if ( CompVal(base, target, inCompMode) ){
				SORT_DATA data;
				//データ入れ替え
				data = ioSortDatAry[i-1];
				ioSortDatAry[i-1] = ioSortDatAry[i];
				ioSortDatAry[i] = data;
			}else{
				break;
			}
		}
	}
}

//---------------------------------------------------------------------------
/**
 * @brief	ベストファイブデータ書き込み　一人用
 *
 * @param	work			ポケスロンワークポインタ
 * @param	evt_data		競技データポインタ
 * @param	ioSortDatAry	ソートデータ配列
 *
 * @return	none
 */
//---------------------------------------------------------------------------
static void WriteBestFiveDataAlone(PKTHLN_PTR work, PKTH_EVT_DATA *evt_data, const SORT_DATA *inSortDatAry)
{
	int i,n;
	u8 my_net_id;
	PKTHLN_SVSET_DATA * svset;
	svset = &work->SvSetData;
	my_net_id = PTFrameGetCurrentID(work);
	for(i=0;i<BEST_FIVE;i++){
		evt_data->RcMs[i].Record = inSortDatAry[i].Record;
		for (n=0;n<ENTRY_MAX;n++){
			evt_data->RcMs[i].FrmMnsNo[n] = inSortDatAry[i].FrmMnsNo[n];
		}
	}
}

//---------------------------------------------------------------------------
/**
 * @brief	ベストファイブデータ書き込み　通信用
 *
 * @param	work			ポケスロンワークポインタ
 * @param	evt_data		通信競技データポインタ
 * @param	ioSortDatAry	ソートデータ配列
 *
 * @return	none
 */
//---------------------------------------------------------------------------
static void WriteBestFiveDataComm(PKTHLN_PTR work, PKTH_COMM_EVT_DATA *comm_evt_data, const SORT_DATA *inSortDatAry)
{
	int i,n,l;
	for(i=0;i<BEST_FIVE;i++){
		comm_evt_data->EvtData.RcMs[i].Record = inSortDatAry[i].Record;
		for (n=0;n<ENTRY_MAX;n++){
			comm_evt_data->EvtData.RcMs[i].FrmMnsNo[n] = inSortDatAry[i].FrmMnsNo[n];
		}
		comm_evt_data->TrData[i].TrID = inSortDatAry[i].TrID;
		for(l=0;l<BUFLEN_PERSON_NAME;l++){
			comm_evt_data->TrData[i].TrName[l] = inSortDatAry[i].TrName[l];
		}
		comm_evt_data->TrData[i].CountryCode = inSortDatAry[i].CountryCode;
	}
}

#if 0
//---------------------------------------------------------------------------
/**
 * @brief	レコードのバブルソート　一人データ用
 *
 * @param	inCompMode	比較方法
 * @param	inRcms		ポケモン・レコードデータ
 * @param	ioData		格納先データポインタ
 *
 * @return	none
 */
//---------------------------------------------------------------------------
static void BableSortAlone( const COMP_MODE inCompMode,
							PKTH_EVT_RCMS *inRcms,
							PKTH_EVT_DATA *ioData )
{
	int i;
	int base, target;
	//ベストファイブのレコードと今回のレコードを比較
	base = ioData->RcMs[BEST_FIVE-1].Record;
	target = inRcms->Record;
	if ( CompVal(base, target, inCompMode) ){
		//ベストファイブを上書き
		ioData->RcMs[BEST_FIVE-1] = *inRcms;
		//バブルソート
		for(i=BEST_FIVE-1;i>0;i--){
			base = ioData->RcMs[i-1].Record;
			target = ioData->RcMs[i].Record;
			if ( CompVal(base, target, inCompMode) ){
				PKTH_EVT_RCMS rcms;
				//データ入れ替え
				rcms = ioData->RcMs[i-1];
				ioData->RcMs[i-1] = ioData->RcMs[i];
				ioData->RcMs[i] = rcms;
			}else{
				break;
			}
		}
	}
}

//---------------------------------------------------------------------------
/**
 * @brief	レコードのバブルソート　通信データ用
 *
 * @param	inCompMode	比較方法
 * @param	inTrData	トレーナーデータ
 * @param	inRcms		ポケモン・レコードデータ
 * @param	ioData		格納先データポインタ
 *
 * @return	none
 */
//---------------------------------------------------------------------------
static void BableSortComm(	const COMP_MODE inCompMode,
							PKTH_TR_DATA *inTrData, PKTH_EVT_RCMS *inRcms,
							PKTH_COMM_EVT_DATA *ioData	)
{
	int i;
	int base, target;
	//ベストファイブのレコードと今回のレコードを比較
	base = ioData->EvtData.RcMs[BEST_FIVE-1].Record;
	target = inRcms->Record;
	if ( CompVal(base, target, inCompMode) ){
		//ベストファイブを上書き
		ioData->EvtData.RcMs[BEST_FIVE-1] = *inRcms;
		ioData->TrData[BEST_FIVE-1] = *inTrData;
		//バブルソート
		for(i=BEST_FIVE-1;i>0;i--){
			base = ioData->EvtData.RcMs[i-1].Record;
			target = ioData->EvtData.RcMs[i].Record;
			if ( CompVal(base, target, inCompMode) ){
				PKTH_TR_DATA tr_data;
				PKTH_EVT_RCMS rcms;
				//データ入れ替え
				tr_data = ioData->TrData[i-1];
				rcms = ioData->EvtData.RcMs[i-1];
				ioData->TrData[i-1] = ioData->TrData[i];
				ioData->EvtData.RcMs[i-1] = ioData->EvtData.RcMs[i];
				ioData->TrData[i] = tr_data;
				ioData->EvtData.RcMs[i] = rcms;
			}else{
				break;
			}
		}
	}
}
#endif

//---------------------------------------------------------------------------
/**
 * @brief	値の比較
 *
 * inCompModeで戻り値分岐
 * 			COMP_LARGE:比較元より、比較対象が大きければ、TRUE	それ以外FALSE
 *			COMP_SMALL:比較元より、比較対象が小さければ、TRUE	それ以外FALSE
 * @param	inBase		比較元
 * @param	inTarget	比較対象
 * @param	inCompMode	比較方法
 *
 * @return	BOOL
 */
//---------------------------------------------------------------------------
static BOOL CompVal(const int inBase, const int inTarget, const COMP_MODE inCompMode)
{
	BOOL rc = FALSE;

	if (inBase == REC_NO_DATA){		//データの中身が無い場合はＯＫ
		rc = TRUE;
	}else{
		rc = CompValCore(inBase, inTarget, inCompMode);
	}
	return rc;
}

//---------------------------------------------------------------------------
/**
 * @brief	値の比較
 *
 * inCompModeで戻り値分岐
 * 			COMP_LARGE:比較元より、比較対象が大きければ、TRUE	それ以外FALSE
 *			COMP_SMALL:比較元より、比較対象が小さければ、TRUE	それ以外FALSE
 * @param	inBase		比較元
 * @param	inTarget	比較対象
 * @param	inCompMode	比較方法
 *
 * @return	BOOL
 */
//---------------------------------------------------------------------------
static BOOL CompValCore(const int inBase, const int inTarget, const COMP_MODE inCompMode)
{
	BOOL rc = FALSE;
	if (inCompMode == COMP_LARGE){
		if (inBase == REC_NO_DATA){		//データの中身が無い場合はＯＫ
			rc = TRUE;
		}else if (inBase < inTarget){
			rc = TRUE;
		}
	}else if (inCompMode == COMP_SMALL){
		if (inBase == REC_NO_DATA){		//データの中身が無い場合はＯＫ
			rc = TRUE;
		}else if (inBase > inTarget){
			rc = TRUE;
		}
	}else{
		GF_ASSERT(0);
	}
	return rc;
}

//---------------------------------------------------------------------------
/**
 * @brief	セーブデータへランキングデータを反映
 *
 * @param	work			ポケスロンワークポインタ
 * @param	outRankData		ランキングデータ格納バッファポインタ
 *
 * @return	none
 */
//---------------------------------------------------------------------------
static void MakeRankData(PKTHLN_PTR work, PKTH_RNK_DATA *outRankData)
{
	u8 i;
	PKTHLN_SVSET_DATA *svset_data = &work->SvSetData;
	u8 my_net_id = PTFrameGetCurrentID(work);
	//通信・非通信で分岐
	if ( work->LinkData.Header->GameType == PKTHLN_GAME_COMM ){		//通信
		//プレイ回数加算
		AddValLimitCheck( 1, COMM_PLAY_MAX, &outRankData->CommPlay );
		if (svset_data->CrsWin){
			//優勝回数加算
			AddValLimitCheck( 1, COMM_WIN_MAX, &outRankData->CommWin );
			//優勝ポケをセーブデータに記憶
			SetWinPoke(work);
		}else if ( svset_data->CrsLose ){
			//最下位回数加算
			AddValLimitCheck( 1, COMM_LOSE_MAX, &outRankData->CommLose );
		}
	}else{		//非通信
		//プレイ回数加算
		AddValLimitCheck( 1, ALONE_PLAY_MAX, &outRankData->AlonePlay );
		if ( svset_data->CrsWin ){
			//優勝回数加算
			AddValLimitCheck( 1, ALONE_WIN_MAX, &outRankData->AloneWin );
			//優勝ポケをセーブデータに記憶
			SetWinPoke(work);
		}else if( svset_data->CrsLose ){
			//最下位回数加算
			AddValLimitCheck( 1, ALONE_LOSE_MAX, &outRankData->AloneLose );
		}
	}

	//競技回数分ループ
	for (i=0;i<work->EventMax;i++){
		if ( svset_data->EvtWin[i] ){		//各競技優勝回数加算
			u8 evt_code = work->CommCmnData.EventNo[i];
			AddValLimitCheck( 1, EVT_WIN_MAX, &(outRankData->EvtWinNum[ evt_code ]) );
		}else if ( svset_data->EvtLose[i] ){	//競技最下位回数加算
			AddValLimitCheck( 1, EVT_LOSE_MAX, &outRankData->EvtLoseNum );
		}
	}

	//ポケモンアクションデータセット
	for (i=0;i<ENTRY_MAX;i++){
		PKTHLN_POKE_RSLT *poke_rslt = &(svset_data->PokeRslt[my_net_id][i]);

		AddValLimitCheck( poke_rslt->Fail, FAIL_MAX, &outRankData->PokeFail );
		AddValLimitCheck( poke_rslt->Jump, JUMP_MAX, &outRankData->PokeJump );
		AddValLimitCheck( poke_rslt->Get, GET_MAX, &outRankData->PointGet );
		AddValLimitCheck( poke_rslt->Attack, ATTACK_MAX, &outRankData->PokeAttack );
		AddValLimitCheck( poke_rslt->Fall, FALL_MAX, &outRankData->PokeFall );
		AddValLimitCheck( poke_rslt->Dash, DASH_MAX, &outRankData->PokeDash );
		AddValLimitCheck( poke_rslt->Change, CHG_MAX, &outRankData->PokeChange );
		AddValLimitCheck( poke_rslt->OwnGoal, OWN_MAX, &outRankData->OwnGoal );
	}

	//ボーナス取得回数加算
	AddValLimitCheck( svset_data->BonusNum, BOUNUS_MAX, &outRankData->BonusNum );
	//タッチ回数加算
	AddValLimitCheck( svset_data->Touch, TOUCH_MAX, &outRankData->TouchNum );
}

//--------------------------------------------------------------------------------------------
/**
 *	自分の参加ポケを優勝ポケデータにセット
 *
 * @param	work		ポケスロンワークポインタ
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void SetWinPoke(PKTHLN_PTR work)
{
	u8 n;
	PKTH_WIN_POKE* p_w_data = PkthlnWPokeSv_GetSaveData(work->LinkData.Header->SaveData);
	u8 my_net_id = PTFrameGetCurrentID(work);
	POKETHLON_ENTRY_DATA *data = work->CommCmnData.PlayerData[my_net_id].EntryData;

	for(n=0;n<ENTRY_MAX;n++){
		p_w_data[n].MonsNo = data[n].MonsNo;
		p_w_data[n].Form = data[n].Form;
		p_w_data[n].Sex = data[n].Sex;
	}
}

//---------------------------------------------------------------------------
/**
 * @brief	リミットつき値加算処理
 *
 * @param	inVal		加算値
 * @param	inLimit		リミット値
 * @param	ioBuf		バッファ
 *
 * @return	none
 */
//---------------------------------------------------------------------------
static void AddValLimitCheck( const u32 inVal, const u32 inLimit, u32 *ioBuf )
{
	if ( (*ioBuf) + inVal > inLimit ){
		(*ioBuf) = inLimit;
	}else{
		(*ioBuf)+=inVal;
	}
}

//---------------------------------------------------------------------------
/**
 * @brief	メダルの取得
 *
 * @param	work			ポケスロンワークポインタ
 *
 * @return	none
 */
//---------------------------------------------------------------------------
static void SetMedal(PKTHLN_PTR work)
{

	switch(work->LinkData.Header->CourseID){
	case CRS_ID_SPD:			//スピード
		SetMyPokeMedal(work, MEDAL_SPD_BIT);
		break;
	case CRS_ID_POW:			//パワー
		SetMyPokeMedal(work, MEDAL_POW_BIT);
		break;
	case CRS_ID_TEQ:			//テクニック
		SetMyPokeMedal(work, MEDAL_TEQ_BIT);
		break;
	case CRS_ID_STA:			//スタミナ
		SetMyPokeMedal(work, MEDAL_STA_BIT);
		break;
	case CRS_ID_JMP:			//ジャンプ
		SetMyPokeMedal(work, MEDAL_JMP_BIT);
		break;

	case CRS_ID_SPD_JMP:		//スピード・ジャンプ
		SetMyPokeMedal(work, MEDAL_SPD_BIT|MEDAL_JMP_BIT);
		break;
	case CRS_ID_JMP_TEQ:		//ジャンプ・テクニック
		SetMyPokeMedal(work, MEDAL_JMP_BIT|MEDAL_TEQ_BIT);
		break;
	case CRS_ID_TEQ_POW:		//テクニック・パワー
		SetMyPokeMedal(work, MEDAL_TEQ_BIT|MEDAL_POW_BIT);
		break;
	case CRS_ID_POW_STA:		//パワー・スタミナ
		SetMyPokeMedal(work, MEDAL_POW_BIT|MEDAL_STA_BIT);
		break;
	case CRS_ID_STA_SPD:		//スタミナ・スピード
		SetMyPokeMedal(work, MEDAL_STA_BIT|MEDAL_SPD_BIT);
		break;
	}
}

//---------------------------------------------------------------------------
/**
 * @brief	自ポケのメダルの取得
 *
 * @param	work			ポケスロンワークポインタ
 * @param	inMask			メダルマスク
 *
 * @return	none
 */
//---------------------------------------------------------------------------
static void SetMyPokeMedal(PKTHLN_PTR work, const u8 inMask)
{
	u8 i;
	PKTHLN_SV_DATA_PTR save = PkthlnSv_GetSaveData(work->LinkData.Header->SaveData);
	for(i=0;i<ENTRY_MAX;i++){
		PkthlnSv_SetMedalDataByBit(save, inMask, work->LinkData.CmnPlayerData.EntryData[i].MonsNo);
	}
}

//---------------------------------------------------------------------------
/**
 * @brief	一人用コースすべてで優勝しているか（記録に0以外の値が入っているか）を調べる
 *
 * @param	inCourseData	コースデータ先頭アドレス
 *
 * @return	BOOL			TRUEで一人用コースすべてで優勝している
 */
//---------------------------------------------------------------------------
static BOOL CheckAloneCrsWin(const PKTH_COURSE * inCourseData)
{
	u8 i;
	const PKTH_COURSE * course_data;

	for (i=0;i<ALONE_COURSE_NUM;i++){
		course_data = &inCourseData[i];
		//コースデータの最大スコアに0より大きな値が入っていれば、1度はそのコースで優勝したとみなせる
		if (course_data->MaxScore <= 0){
			return FALSE;
		}
	}
	return TRUE;
}

//---------------------------------------------------------------------------
/**
 * @brief	今回のポケがすべてのメダルを持っているかをチェック
 *
 * @param	work			ポケスロンワークポインタ
 *
 * @return	BOOL			TRUEでメダル持っている
 */
//---------------------------------------------------------------------------
static BOOL	CheckOnePokeAllMedal(PKTHLN_PTR work)
{
	u8 i;
	const u8 *medal;
	PKTHLN_SV_DATA_PTR save = PkthlnSv_GetSaveData(work->LinkData.Header->SaveData);
	for(i=0;i<ENTRY_MAX;i++){
		int idx = work->LinkData.CmnPlayerData.EntryData[i].MonsNo-1;
		medal = PkthlnSv_GetMedalDataCnst(save);
		if (medal[idx] == MEDAL_ALL_BIT_MASK){
			return TRUE;
		}
	}
	return FALSE;
}

//---------------------------------------------------------------------------
/**
 * @brief	デフォルト記録をすべて塗り替えたかをチェック
 *
 * @param	work			ポケスロンワークポインタ
 *
 * @return	BOOL			TRUE:デフォルト記録をすべて塗り替えた
 */
//---------------------------------------------------------------------------
static BOOL	CheckDefaultRecordUpdate(PKTHLN_PTR work)
{
	u8 i;
	PKTH_EVT_DATA *evt_data;
	PKTHLN_SV_DATA_PTR save = PkthlnSv_GetSaveData(work->LinkData.Header->SaveData);

	evt_data = PkthlnSv_GetEvtDataAlone(save);
	for (i=0;i<PKTHLN_EVT_MAX;i++){
		u16 rec = evt_data[i].RcMs[0].Record;
		OS_Printf("第%d競技ベスト1 :%d\n",i, rec);
		if (rec == REC_NO_DATA){
			return FALSE;
		}else{
			if ( !CompValCore(DefautlRec[i], rec, SortComp[i]) ){
				return FALSE;
			}
		}
	}
	return TRUE;
}

//---------------------------------------------------------------------------
/**
 * @brief	ヘッダー情報から、今回の競技を決定
 *
 * @param	inHeader		ヘッダー情報
 * @param	inEvtMax		競技数
 * @param	outEvt			競技格納バッファ
 *
 * @return	none
 */
//---------------------------------------------------------------------------
static void DecideEvt(const POKETHLON_HEADER *inHeader, const u8 inEvtMax, u8 *outEvt)
{
	u8 i;
	u8 course_id;
	BOOL rc = FALSE;
	//初期化
	for(i=0;i<PKTHLN_GAME_COMM;i++){
		outEvt[i] = PKTHLN_EVT_NONE;
	}

	course_id = inHeader->CourseID;
#ifdef PM_DEBUG
	//デバッグフラグ有効ならば、コース書き換え
	if (DebugPkthlnWk.Flg){
		course_id = DebugPkthlnWk.Crs;
	}
#endif

	//通信・非通信で分岐
	if (inHeader->GameType == PKTHLN_GAME_COMM){	//通信
		switch(course_id){
		case CRS_ID_SPD_JMP:
		case CRS_ID_JMP_TEQ:
		case CRS_ID_TEQ_POW:
		case CRS_ID_POW_STA:
		case CRS_ID_STA_SPD:
		case CRS_ID_MAS:
			rc = TRUE;
			break;
		default:
			GF_ASSERT_MSG(0, "コースID：%d　通信では識別できません\n",course_id);
		}
	}else{							//非通信
		switch(course_id){
		case CRS_ID_SPD:
		case CRS_ID_POW:
		case CRS_ID_TEQ:
		case CRS_ID_STA:
		case CRS_ID_JMP:
#ifdef PM_DEBUG
		case CRS_ID_MAS:		//デバッグ時のみ非通信マスターコースあり
#endif
			rc = TRUE;
			break;
		default:
			GF_ASSERT_MSG(0, "コースID：%d　通信では識別できません\n",course_id);
		}
	}

	if (rc){
		if ( course_id == CRS_ID_MAS ){
			//競技をランダム選出
			u8 no = gf_rand()%MAS_NO_NUM;
			for(i=0;i<inEvtMax;i++){
				outEvt[i] = mas_crs_evt_tbl[no][i];
			}
#ifdef PM_DEBUG
			//デバッグフラグ有効ならば、デバッグ指定競技で書き換え
			if (DebugPkthlnWk.Flg){
				for(i=0;i<inEvtMax;i++){
					outEvt[i] = DebugPkthlnWk.Evt[i];
				}
			}
#endif
		}else{
			for(i=0;i<inEvtMax;i++){
				outEvt[i] = crs_evt_tbl[course_id][i];
			}
		}
	}else{
#ifdef PM_DEBUG
		//デバッグ情報から競技を決定
		for(i=0;i<inEvtMax;i++){
			outEvt[i] = DebugPkthlnWk.Evt[i];
		}
#endif
	}
}

//--------------------------------------------------------------------------------------------
/**
 * 競技共通▼マーカータスク
 *
 * @param	tcb		TCB
 * @param	work	ワークポインタ
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void PosMarkerTask(TCB_PTR tcb, void* work)
{
	int x,y;
	VecFx32 vec;
	POS_MARKER *marker = (POS_MARKER *)work;
	//ポケモンの座標を取得
	PokeAct_GetCPos(marker->PokePtr, &x, &y );
	//マーカー座標更新
	CLACT_SetDrawFlag(marker->ActPtr, 1);
	vec.z = 0;
	vec.x = x*FX32_ONE;
	vec.y = y*FX32_ONE;
	CLACT_SetMatrix( marker->ActPtr, &vec );

	//ポケの表示状態を取得
	if ( PokeAct_GetDrawFlg(marker->PokePtr) ){
		CLACT_SetDrawFlag(marker->ActPtr, 1);
	}else{
		CLACT_SetDrawFlag(marker->ActPtr, 0);
	}
}

//--------------------------------------------------------------------------------------------
/**
 * アクションデータのカウントアップ
 *
 * @param	work			ポケスロンポインタ
 * @param	inNetID			ネットＩＤ
 * @param	inPokeIdx		ポケモンインデックス（0〜2）
 * @param	inAddType		追加タイプ
 * @param	inAddVal		追加値
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
void PTFrame_AddActionPoint(PKTHLN_PTR work,
							const u8 inNetID, const u8 inPokeIdx,
							const ACTION_ADD_TYPE inAddType, const int inAddVal)
{
	PKTHLN_POKE_RSLT *rslt;

	if ( inAddType == ADD_TYPE_TOUCH ){
		//自分自身にしか加算できない
		GF_ASSERT_MSG( (PTFrameGetCurrentID(work) == inNetID),"タッチ回数は自分でカウントすること\n" );
		GF_ASSERT_MSG( inAddVal == 1,"タッチ回数は1ずつインクリメント\n" );
		if (work->SvSetData.Touch < ACTION_ADD_MAX){
			work->SvSetData.Touch++;
		}
		return ;
	}

	GF_ASSERT(inPokeIdx < ENTRY_MAX);

	//今回競技は、親集計型か？
	if (!work->FuncTbl->ResultSend){		//親集計型
		GF_ASSERT_MSG( (PTFrameGetCurrentID(work) == COMM_PARENT_ID),"対象ID＝%d 今回の競技は親集計\n",inAddType );
		rslt = &(work->SvSetData.PokeRslt[inNetID][inPokeIdx]);
		AddActionPoint(inAddType, inAddVal, rslt);
	}else {									//個々集計型
		if ( PTFrameGetCurrentID(work) == COMM_PARENT_ID ){ 	//親はＮＰＣの集計もする
			//加算はＮＰＣか？
			if (inNetID >= PTFrame_GetPlayerNum(work)){
				//親がＮＰＣに加算
				rslt = &(work->SvSetData.PokeRslt[inNetID][inPokeIdx]);
				AddActionPoint(inAddType, inAddVal, rslt);
			}else{
				//親が自分自身に加算
				GF_ASSERT_MSG( (PTFrameGetCurrentID(work)==inNetID),"対象ID＝%d 親が他人に加算しようとしている\n",inAddType );
				rslt = &(work->EvtActionTmp[inPokeIdx]);
				AddActionPoint(inAddType, inAddVal, rslt);
			}
		}else{
			//加算は自分自身のはず
			GF_ASSERT_MSG( (PTFrameGetCurrentID(work)==inNetID),"対象ID＝%d  子か他人に加算しようとしている\n",inAddType );
			rslt = &(work->EvtActionTmp[inPokeIdx]);
			AddActionPoint(inAddType, inAddVal, rslt);
		}
	}
}

//--------------------------------------------------------------------------------------------
/**
 * ニューレコード判定用レコードをセット
 *
 * @param	work			ポケスロンポインタ
 * @param	inRecord
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
void PTFrame_SetCheckRecord(PKTHLN_PTR work, const u16 inRecord)
{
	work->CheckRecord = inRecord;
}

//--------------------------------------------------------------------------------------------
/**
 * レコードコールバック関数登録
 *
 * @param	work			ポケスロンポインタ
 * @param	func			コールバック関数
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
void PTFrame_SetRecordCallBack(PKTHLN_PTR work, REC_CALL_BACK func)
{
	GF_ASSERT( work->RecordCallBack == NULL );
	work->RecordCallBack = func;
}


//--------------------------------------------------------------------------------------------
/**
 * アクションデータのカウントアップ
 *
 * @param	inAddType		追加タイプ
 * @param	inAddVal		追加値
 * @param	outRslt			格納構造体ポインタ
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void AddActionPoint(const ACTION_ADD_TYPE inAddType, const u8 inAddVal, PKTHLN_POKE_RSLT *outRslt)
{
	u32 *target;

	switch(inAddType){
	case ADD_TYPE_FAIL:
		target = &outRslt->Fail;
		break;
	case ADD_TYPE_JUMP:
		target = &outRslt->Jump;
		break;
	case ADD_TYPE_GET:
		target = &outRslt->Get;
		break;
	case ADD_TYPE_ATTACK:
		target = &outRslt->Attack;
		break;
	case ADD_TYPE_FALL:
		target = &outRslt->Fall;
		break;
	case ADD_TYPE_DASH:
		target = &outRslt->Dash;
		break;
	case ADD_TYPE_CHANGE:
		target = &outRslt->Change;
		break;
	case ADD_TYPE_OWN:
		target = &outRslt->OwnGoal;
		break;
	default:
		GF_ASSERT(0);
		return;
	}

	(*target) += inAddVal;
	//リミットチェック
	if ( *target > ACTION_ADD_MAX ){
		*target = ACTION_ADD_MAX;
	}
}

//--------------------------------------------------------------------------------------------
/**
 * ニューレコード判定
 *
 * @param	work		ポケスロンポインタ
 *
 * @return	BOOL		TRUEで記録更新
 */
//--------------------------------------------------------------------------------------------
static BOOL CheckNewRecord(PKTHLN_PTR work)
{
	u16 *best_rec;
	PKTHLN_EVT_CODE evt_code;
	PKTH_EVT_DATA *evtData;
	PKTHLN_SV_DATA_PTR save = PkthlnSv_GetSaveData(work->LinkData.Header->SaveData);

	OS_Printf("check_rec = %d\n",work->CheckRecord);

	if (work->CheckRecord == REC_NO_DATA){
		GF_ASSERT_MSG(0,"比較のためのレコードがセットされていない\n");
		return FALSE;
	}

	//種目コード取得
	evt_code =  PTFrame_GetEventCode(work);
	//通信か非通信かで参照データを分岐
	if (work->LinkData.Header->GameType == PKTHLN_GAME_COMM){		//通信
		PKTH_COMM_EVT_DATA *comm_evtData;
		comm_evtData = PkthlnSv_GetEvtDataComm(save);
		evtData = &comm_evtData[evt_code].EvtData;
		best_rec = &evtData->RcMs[0].Record;
	}else{
		evtData = PkthlnSv_GetEvtDataAlone(save);
		best_rec = &evtData[evt_code].RcMs[0].Record;
	}

	OS_Printf("best_rec = %d\n",*best_rec);

	if (*best_rec == REC_NO_DATA){
		return TRUE;
	}

	//競技毎に大小比較方法を変える
	if (SortComp[evt_code] == COMP_LARGE){	//値の大きい方が良いレコード
		if (*best_rec < work->CheckRecord){
			return TRUE;
		}
	}else{	//値の小さい方が良いレコード
		if (*best_rec > work->CheckRecord){
			return TRUE;
		}
	}
	return FALSE;
}

//--------------------------------------------------------------------------------------------
/**
 * ＮＰＣＯＢＪコードを返す
 *
 * @param	inNpcCode		NPCコード
 *
 * @return	u16				OBJコード
 */
//--------------------------------------------------------------------------------------------
u16 PTFrame_GetNpcObjCode(const u8 inNpcCode)
{
	u8 idx;
	if ( (inNpcCode > 0)&&( inNpcCode <= NORM_NPC_NUM+SP_NPC_NUM ) ){
		idx = inNpcCode-1;
		return NpcObjCode[idx];
	}else{
		GF_ASSERT(0);
		return 0;
	}
}

//--------------------------------------------------------------------------------------------
/**
 * ＮＰＣメッセージＩＤを返す
 *
 * @param	work		ポケスロンポインタ
 * @param	inNpcCode	NPCコード
 *
 * @return	メッセージID
 */
//--------------------------------------------------------------------------------------------
u32 PTFrame_GetNpcMsgIdx(PKTHLN_PTR work, const u8 inNpcCode)
{
	if ( (inNpcCode > 0)&&( inNpcCode <= NORM_NPC_NUM+SP_NPC_NUM ) ){
		ARCHANDLE* npc_handle;
		NPC_DATA npc_data;
		//NPCアーカイブハンドル開く
		npc_handle = ArchiveDataHandleOpen( ARC_PKTH_NPC_DATA, PTFrame_GetHeapID(work) );
		//データを格納
		ArchiveDataLoadByHandle( npc_handle, inNpcCode-1, &npc_data );
		//ハンドルクローズ
		ArchiveDataHandleClose( npc_handle );
		return npc_data.MsgGmmIdx;
	}else{
		GF_ASSERT(0);
		return 0;
	}
}

//--------------------------------------------------------------------------------------------
/**
 * ＮＰＣ作成
 *
 * @param	ptr		ポケスロンポインタ
 * @param	inNum	NPC数
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
void PTFrame_MakeNPCData(PKTHLN_PTR ptr, const u8 inNum)
{
	int i,j,k;
	MSGDATA_MANAGER *msgman;
	int start;
	ARCHANDLE* handle;
	ARCHANDLE* npc_handle;
	u8 npc_code[ENTRY_MEMBER_NUM_MAX-1];

	//メッセージマネージャ作成
	msgman = MSGMAN_Create(MSGMAN_TYPE_DIRECT, ARC_MSG, NARC_msg_pokethlon_cname_dat, PTFrame_GetHeapID(ptr));

	start = ENTRY_MEMBER_NUM_MAX - inNum;
	//ＮＰＣコードを決定する
	MakeNpcCode(inNum, ptr->LinkData.Header->CourseID, ptr->LinkData.Header->AllStar, npc_code);
	//アーカイブハンドルを開く
	handle = ArchiveDataHandleOpen( ARC_PKTHPOKE_PARAM, PTFrame_GetHeapID(ptr) );
	//NPCアーカイブハンドル開く
	npc_handle = ArchiveDataHandleOpen( ARC_PKTH_NPC_DATA, PTFrame_GetHeapID(ptr) );
	//人数を引数でもらう
	for(j=0,i=start;i<ENTRY_MEMBER_NUM_MAX;i++,j++){
		//アーカイブ取得
		COMMON_PLAYER_DATA *data;
		STRBUF* strbuf;
		MYSTATUS *my_st;
		NPC_DATA npc_data;

		data = PTFrame_GetCmnPlayerDataPtrByID(ptr, i);
		data->PersonCode = npc_code[j];		//NPC識別子

		GF_ASSERT(data->PersonCode != 0);

		//データを格納
		ArchiveDataLoadByHandle( npc_handle, data->PersonCode-1, &npc_data );

		OS_Printf("name = %d, msg = %d\n", npc_data.NameGmmIdx, npc_data.MsgGmmIdx);

		strbuf = MSGMAN_AllocString( msgman, npc_data.NameGmmIdx);
		my_st = PTFrame_GetMyStatus(ptr, i);
		MyStatus_SetMyName(my_st, STRBUF_GetStringCodePointer( strbuf ));
		STRBUF_Delete( strbuf );

		for(k=0;k<ENTRY_MAX;k++){
			//参加ポケモンを決定
			data->EntryData[k].MonsNo = npc_data.MonsNo[k];
			data->EntryData[k].Form = 0;
			data->EntryData[k].Rare = 0;
			data->EntryData[k].PsnlRnd = 0;
#ifdef	PM_DEBUG
#ifdef	DEBUG_NPC_POKE
			data->EntryData[k].MonsNo = DebugNpcMonsNo[j][k];
#endif
#endif
			//性別決定
			{
				u8	sex_vec;
				u8 sex;
				sex_vec = PokePersonalParaGet(data->EntryData[k].MonsNo, ID_PER_sex);
				switch(sex_vec){
				case	MONS_MALE:		//オスのみ
					sex = PARA_MALE;
					break;
				case	MONS_FEMALE:	//メスのみ
					sex = PARA_FEMALE;
					break;
				case	MONS_UNKNOWN:	//性別なし
					sex = PARA_UNK;
					break;
				default:				//オスメス存在する場合はオスをセット
					sex = PARA_MALE;
				}
				data->EntryData[k].Sex = sex;
			}
			//スペック
			{
				int monsno,idx;
				PKTHPOKE_PARAM param;
				monsno = data->EntryData[k].MonsNo;
				//アーカイブインデックス取得
				idx = PTFrame_GetPokeParamArcIdx(monsno, 0);
				//データを格納
				ArchiveDataLoadByHandle( handle, idx, &param );
				data->EntryData[k].Spec.Power = param.Power;
				data->EntryData[k].Spec.Speed = param.Speed;
				data->EntryData[k].Spec.Jump = param.Jump;
				data->EntryData[k].Spec.Stamina = param.Stamina;
				data->EntryData[k].Spec.Technique = param.Technique;
			}

			{
				STRBUF *name_buf;
				name_buf = MSGDAT_UTIL_GetMonsName( npc_data.MonsNo[k], PTFrame_GetHeapID(ptr) );
				PM_strncpy( data->EntryData[k].NickName, STRBUF_GetStringCodePointer( name_buf ), MONS_NAME_SIZE+EOM_SIZE );
				STRBUF_Delete(name_buf);
			}
		}
	}
	//ハンドルクローズ
	ArchiveDataHandleClose( npc_handle );
	//ハンドルクローズ
	ArchiveDataHandleClose( handle );

	MSGMAN_Delete(msgman);
}

//--------------------------------------------------------------------------------------------
/**
 * ＮＰＣコードの決定
 *
 * @param	inNpcNum	NPC数
 * @param	inCrsID		コースＩＤ
 * @param	inAllStar	オールスターフラグ
 * @param	outNpcCode	格納バッファ
 *
 * @return	none
 */
//--------------------------------------------------------------------------------------------
static void MakeNpcCode(const u8 inNpcNum, const CRS_ID inCrsID, const BOOL inAllStar, u8 *outNpcCode)
{
	u8 i;

	//クリア
	for(i=0;i<ENTRY_MEMBER_NUM_MAX-1;i++){
		outNpcCode[i] = 0;
	}

	//マスターコースの場合は全データからランダム抽選
	if (inCrsID == CRS_ID_MAS){		//マスター
		u8 n;
		u8 crs_npc[COMM_ALL_NPC_NUM];
		u8 crs_npc_num = COMM_ALL_NPC_NUM;
		for (n=0;n<COMM_ALL_NPC_NUM;n++){
			crs_npc[n] = n;
		}
		for(n=0;n<inNpcNum;n++){
			u8 rnd;
			rnd = gf_rand()%crs_npc_num;
			outNpcCode[n] = crs_npc[rnd];
			outNpcCode[n] += MAS_CRS_OFS;	//マスターコースオフセット
			//抽選幅縮小
			crs_npc_num--;
			crs_npc[rnd] = crs_npc[crs_npc_num];
		}
	}else{		//マスター以外
		u8 n;
		u8 crs_npc[CRS_NPC_NUM];
		u8 crs_npc_num = CRS_NPC_NUM;
		for (n=0;n<CRS_NPC_NUM;n++){
			crs_npc[n] = n;
		}
		for(n=0;n<inNpcNum;n++){
			u8 rnd;
			rnd = gf_rand()%crs_npc_num;
			outNpcCode[n] = crs_npc[rnd];
			//コースオフセットをつける
			outNpcCode[n] += (inCrsID*CRS_NPC_NUM);
			//抽選幅縮小
			crs_npc_num--;
			crs_npc[rnd] = crs_npc[crs_npc_num];
		}
	}

	//オールスターかどうかでオフセット加算
	if (inAllStar){
		u8 n;
		for(n=0;n<inNpcNum;n++){
			outNpcCode[n] += ALLSTAR_NPC_OFS;
		}
	}

	//1オリジン
	for(i=0;i<inNpcNum;i++){
		outNpcCode[i] ++;
	}

#ifdef PM_DEBUG
	//NPCはかぶらないはず
	if ( (outNpcCode[0] != 0)&&outNpcCode[1] != 0 ){
		GF_ASSERT( outNpcCode[0]!=outNpcCode[1] );
	}
	if ( (outNpcCode[1] != 0)&&outNpcCode[2] != 0 ){
		GF_ASSERT( outNpcCode[1]!=outNpcCode[2] );
	}
	if ( (outNpcCode[2] != 0)&&outNpcCode[0] != 0 ){
		GF_ASSERT( outNpcCode[2]!=outNpcCode[0] );
	}
#endif
}

//--------------------------------------------------------------------------------------------
/**
 * ジュースデータバッファの先頭アドレスを取得
 *
 * @param	ptr		ポケスロンポインタ
 *
 * @return	void *		先頭アドレス
 */
//--------------------------------------------------------------------------------------------
void *PTFrame_GetJuiceDataAdr(PKTHLN_PTR ptr)
{
	GF_ASSERT(ptr->JuiceData != NULL);
	return ptr->JuiceData;
}

//--------------------------------------------------------------------------------------------
/**
 * ジュースデータバッファの先頭アドレスを取得
 *
 * @param	ptr		ポケスロンポインタ
 * @param	inNetID
 *
 * @return	void *		先頭アドレス
 */
//--------------------------------------------------------------------------------------------
void *PTFrame_GetAllJuiceDataAdr(PKTHLN_PTR ptr, const u8 inNetID)
{
	int size;
	u8 *dat;
	GF_ASSERT(inNetID < 4);
	GF_ASSERT(ptr->AllJuiceData != NULL);
	size = BonguriSave_GetBongJuiceCommWorkSize();
	dat = ptr->AllJuiceData;
	dat += (size*inNetID);
	return dat;
}

//--------------------------------------------------------------------------------------------
/**
 * タッチ判定用計算
 *
 * @param	inPX1			Ｘ座標1
 * @param	inPY1			Ｙ座標1
 * @param	inPX2			Ｘ座標2
 * @param	inPY2			Ｙ座標2
 * @param	inRange			タッチ有効半径
 *
 * @param	outRsltRange	2点間距離
 *
 *
 * @return	BOOL			TRUEで有効範囲内
 */
//--------------------------------------------------------------------------------------------
BOOL PTFrame_CheckTouchRange( const int inPX1, const int inPY1, const int inPX2, const int inPY2,
							  const int inRange, fx32 *outRange)
{
	VecFx32 vec_a, vec_b, dst_vec;
	fx32 len;

	vec_a.x = inPX1*FX32_ONE;
	vec_a.y = inPY1*FX32_ONE;
	vec_a.z = 0;

	vec_b.x = inPX2*FX32_ONE;
	vec_b.y = inPY2*FX32_ONE;
	vec_b.z = 0;

	VEC_Subtract( &vec_a, &vec_b, &dst_vec );
	//方向ベクトルの長さを取得
	len = VEC_Mag(&dst_vec);
	*outRange = len;
	//射程と比較
	if (len < inRange*FX32_ONE){
		//有効範囲内
		return TRUE;
	}
	return FALSE;
}

#ifdef PM_DEBUG
static void PrintActPoint(PKTHLN_PTR work)
{
	u8 i,j;
	PKTHLN_POKE_RSLT *rslt;

	OS_Printf("****************アクションデータをプリント******************\n");
	for (i=0;i<ENTRY_MEMBER_NUM_MAX;i++){
		rslt = PTFrame_GetEvtActDataPtr(work, i);
		OS_Printf("○NetID:%d\n",i);
		for (j=0;j<ENTRY_MAX;j++){
			OS_Printf("　ポケインデックス：%d\n",j);
			OS_Printf("・失敗回数:		%d\n",rslt[j].Fail);
			OS_Printf("・ジャンプ回数:	%d\n",rslt[j].Jump);
			OS_Printf("・ゲット回数:	%d\n",rslt[j].Get);
			OS_Printf("・体当たり回数:	%d\n",rslt[j].Attack);
			OS_Printf("・落下回数:		%d\n",rslt[j].Fall);
			OS_Printf("・ダッシュ回数:	%d\n",rslt[j].Dash);
			OS_Printf("・交代回数:		%d\n",rslt[j].Change);
			OS_Printf("・自滅回数:		%d\n",rslt[j].OwnGoal);
		}
	}
	OS_Printf("****************アンクションデータをプリント終了******************\n");

}

static void PrintLocalActPoint(PKTHLN_PTR work)
{
	u8 j;
	PKTHLN_POKE_RSLT *rslt;

	OS_Printf("****************ローカルアクションデータをプリント******************\n");
	rslt = work->EvtActionTmp;
	for (j=0;j<ENTRY_MAX;j++){
		OS_Printf("　ポケインデックス：%d\n",j);
		OS_Printf("・失敗回数:		%d\n",rslt[j].Fail);
		OS_Printf("・ジャンプ回数:	%d\n",rslt[j].Jump);
		OS_Printf("・ゲット回数:	%d\n",rslt[j].Get);
		OS_Printf("・体当たり回数:	%d\n",rslt[j].Attack);
		OS_Printf("・落下回数:		%d\n",rslt[j].Fall);
		OS_Printf("・ダッシュ回数:	%d\n",rslt[j].Dash);
		OS_Printf("・交代回数:		%d\n",rslt[j].Change);
		OS_Printf("・自滅回数:		%d\n",rslt[j].OwnGoal);
	}
	OS_Printf("****************ローカルアンクションデータをプリント終了******************\n");

}

#endif